WebView完全解读
概述
WebView控件可以在自己的應用程序中顯示本地或者Internet上的網頁。
WebView是一個使用WebKit引擎(4.4之后基于Chromium)的瀏覽器控件。因此可以將WebView當做一個完整的瀏覽器使用。
WebView不僅支持HTML、CSS等靜態元素,還支持JavaScript,而且在JavaScript中還可以調用Java的方法。
官方文檔
Building Web Apps in WebView
常用類:
僅列舉日常開發中常用的幾個類和常用方法,其余請自行查閱官方API。
WebView官方API
WebChromeClient:輔助WebView處理Javascript的對話框、網站圖標、網站title、加載進度等! 部分方法如下:
WebViewClient:輔助WebView處理各種通知與請求事件! 部分方法如下:
WebSettings:WebView相關配置的設置,比如setJavaScriptEnabled()設置是否允許JS腳本執行 部分方法如下:
方法說明:
- loadUrl():直接顯示網頁內容(單獨顯示網絡圖片),一般不會出現亂碼。
- loadData(data, “text/html”, “UTF-8”):用來加載URI格式的數據,不能通過網絡來加載內容, 不能加載圖片,而且經常會遇到亂碼的問題,我們知道String類型的數據主要是Unicode編碼的, 而WebView一般為了節省資源使用的是UTF-8編碼,盡管我們按上面寫了,但是還需要為webView設置: webview.getSettings().setDefaultTextEncodingName(“UTF -8”);
- loadDataWithBaseURL(baseUrl, string, “text/html”, “utf-8”, null):loadData類的一個 增強類,可以加載圖片,baseUrl為你存儲的圖片路徑,而且只需在這里設置utf-8就可以解決亂碼 問題了。
功能演示
加載之前顯示進度框-重寫WebViewClient.onPageStarted()
可以重寫onPageStarted 方法
webView.setWebViewClient(new WebViewClient() {// 設置WebView點擊打開的網頁在當前界面顯示,而不是跳到新的瀏覽器中@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {LogUtils.e("onPageStarted");showProgressDialog();}@Overridepublic void onPageFinished(WebView view, String url) {LogUtils.e("onPageFinished");closeProgressDialog();}@Overridepublic void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {super.onReceivedError(view, request, error);LogUtils.e("onReceivedError");closeProgressDialog();}});根據URL加載網頁-直接在Activity上加載一個WebView
運行圖
WebView00.java
package com.turing.base.activity.webview;import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast;import com.apkfuns.logutils.LogUtils;/*** 根據URL加載網頁-直接在Activity上加載一個WebView*/ public class WebView00 extends AppCompatActivity {private WebView webView;private long exitTime = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 初始化webViewwebView = new WebView(this);webView.setWebViewClient(new WebViewClient() {// 設置WebView點擊打開的網頁在當前界面顯示,而不是跳到新的瀏覽器中@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});// 設置WebView屬性,允許執行JS腳本,不然加載出來的網頁很難看webView.getSettings().setJavaScriptEnabled(true);// 調用LoadUrl,載入urlwebView.loadUrl("http://www.baidu.com");// 調用Activity的setContentView 將webView 顯示出來setContentView(webView);}/*** 重寫回退按鈕的時間,當用戶點擊回退按鈕:* 1.webView.canGoBack()判斷網頁是否能后退,可以則goback()* 2.如果不可以連續點擊兩次退出App,否則彈出提示Toast*/@Overridepublic void onBackPressed() {if (webView.canGoBack()) {webView.goBack();} else {// 第一次的差,肯定大于2S,此時,彈出Toast,將當前時間設置給exitTime,然后再進行比較if (System.currentTimeMillis() - exitTime > 2000) {Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {/*** finish():結束當前Activity,不會立即釋放內存。遵循android內存管理機制。* exit():結束當前組件如Activity,并立即釋放當前Activity所占資源。* killProcess():結束當前組件如Activity,并立即釋放當前Activity所占資源。*/// 并不能徹底退出APP,只是會結束當前Act,釋放資源LogUtils.e("PID:" + android.os.Process.myPid());android.os.Process.killProcess(android.os.Process.myPid());System.exit(0);}}} }根據URL加載網頁-布局代碼中設置WebView
運行圖
WebView01.java
package com.turing.base.activity.webview;import android.annotation.TargetApi; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.TextView; import android.widget.Toast;import com.turing.base.R;public class WebView01 extends AppCompatActivity implements View.OnClickListener {private Button btn_back;private TextView txt_title;private Button btn_top;private Button btn_refresh;private WebView wView;private long exitTime = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view01);btn_back = (Button) findViewById(R.id.btn_back);txt_title = (TextView) findViewById(R.id.txt_title);btn_top = (Button) findViewById(R.id.btn_top);btn_refresh = (Button) findViewById(R.id.btn_refresh);wView = (WebView) findViewById(R.id.wView);// 設置WebView屬性,允許執行JS腳本,不然加載出來的網頁很難看wView.getSettings().setJavaScriptEnabled(true);wView.loadUrl("http://www.baidu.com");wView.setWebChromeClient(new WebChromeClient() {//這里設置獲取到的網站title@Overridepublic void onReceivedTitle(WebView view, String title) {super.onReceivedTitle(view, title);txt_title.setText(title);}});wView.setWebViewClient(new WebViewClient() {//在webview里打開新鏈接@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});btn_back.setOnClickListener(this);btn_refresh.setOnClickListener(this);btn_top.setOnClickListener(this);}@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_back:finish(); //關閉當前Activitybreak;case R.id.btn_refresh:wView.reload(); //刷新當前頁面break;case R.id.btn_top:wView.setScrollY(0); //滾動到頂部break;}}@Overridepublic void onBackPressed() {if (wView.canGoBack()) {wView.goBack();} else {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(getApplicationContext(), "再按一次退出程序",Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {finish();}}}}activity_web_view01.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayout android:layout_width="match_parent"android:layout_height="48dp"android:background="#2D97CB"><Button android:id="@+id/btn_back"android:layout_width="64dp"android:layout_height="48dp"android:layout_alignParentLeft="true"android:background="@android:color/transparent"android:text="Back" /><Button android:id="@+id/btn_top"android:layout_width="64dp"android:layout_height="48dp"android:layout_alignParentRight="true"android:background="@android:color/transparent"android:text="回頂部" /><Button android:id="@+id/btn_refresh"android:layout_width="64dp"android:layout_height="48dp"android:layout_toLeftOf="@id/btn_top"android:background="@android:color/transparent"android:text="刷新" /><TextView android:id="@+id/txt_title"android:layout_width="match_parent"android:layout_height="48dp"android:layout_toLeftOf="@id/btn_refresh"android:layout_toRightOf="@id/btn_back"android:gravity="center"android:singleLine="true"android:text="文章標題"android:textColor="#FFFFFF"android:textSize="18sp" /></RelativeLayout><WebView android:id="@+id/wView"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>WebView滾動事件的監聽
監聽滾動事件一般都是設置setOnScrollChangedListener,可惜的是 WebView并沒有給我們提供這樣的方法,但是我們可以重寫WebView,覆蓋里面的一個方法: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} 然后再對外提供一個接口~
運行圖
MyWebView.java
package com.turing.base.activity.webview;import android.content.Context; import android.util.AttributeSet; import android.webkit.WebView;/*** MyApp** @author Mr.Yang on 2016-03-24 09:37.* @version 1.0* 監聽滾動事件一般都是設置setOnScrollChangedListener,* 可惜的是 WebView并沒有給我們提供這樣的方法,* 但是我們可以重寫WebView,覆蓋里面的一個方法:* protected void onScrollChanged(final int l, final int t,* final int oldl,final int oldt){}* 然后再對外提供一個接口*/ public class MyWebView extends WebView {/*** 接口對象*/private OnScrollChangedCallback onScrollChangedCallback;/*** 構造函數** @param context*/public MyWebView(Context context) {super(context);}/*** 構造函數** @param context*/public MyWebView(Context context, AttributeSet attrs) {super(context, attrs);}/*** 構造函數** @param context*/public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}/*** get方法** @return*/public OnScrollChangedCallback getOnScrollChangedCallback() {return onScrollChangedCallback;}/*** set方法** @param onScrollChangedCallback*/public void setOnScrollChangedCallback(OnScrollChangedCallback onScrollChangedCallback) {this.onScrollChangedCallback = onScrollChangedCallback;}/*** 重寫onScrollChanged方法** @param l* @param t* @param oldl* @param oldt**/@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (onScrollChangedCallback != null) {onScrollChangedCallback.onScroll(l - oldl, t - oldt);}}/*** 對外接口*/public static interface OnScrollChangedCallback {//這里的dx和dy代表的是x軸和y軸上的偏移量,也可以自己把l, t, oldl, oldt四個參數暴露出來public void onScroll(int dx, int dy);} }WebViewScrollChanged.java
package com.turing.base.activity.webview;import android.annotation.TargetApi; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.Toast;import com.turing.base.R;public class WebViewScrollChanged extends AppCompatActivity {private MyWebView myWebView;private Button toTopBtn;private long exitTime = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view_scroll_changed);// 初始化組件myWebView = (MyWebView) findViewById(R.id.id_webview);toTopBtn = (Button) findViewById(R.id.btn_icon);// 加載webViewmyWebView.getSettings().setJavaScriptEnabled(true);myWebView.loadUrl("http://sports.sina.com.cn/");myWebView.setWebViewClient(new WebViewClient() {//在webview里打開新鏈接@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});// 當頁面發生滾動,顯示ButtonmyWebView.setOnScrollChangedCallback(new MyWebView.OnScrollChangedCallback() {@Overridepublic void onScroll(int dx, int dy) {if (dy > 0) {toTopBtn.setVisibility(View.VISIBLE);} else {toTopBtn.setVisibility(View.GONE);}}});toTopBtn.setOnClickListener(new View.OnClickListener() {@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)@Overridepublic void onClick(View v) {myWebView.setScrollY(0);toTopBtn.setVisibility(View.GONE);}});}@Overridepublic void onBackPressed() {if (myWebView.canGoBack()) {myWebView.goBack();} else {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(getApplicationContext(), "再按一次退出程序",Toast.LENGTH_SHORT).show();exitTime = System.currentTimeMillis();} else {finish();}}} }activity_web_view_scroll_changed.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!--使用自定義的WebView方便監聽滾動事件--><com.turing.base.activity.webview.MyWebView android:id="@+id/id_webview"android:layout_width="match_parent"android:layout_height="match_parent"></com.turing.base.activity.webview.MyWebView><Button android:id="@+id/btn_icon"android:layout_width="64dp"android:layout_height="64dp"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:text="回到頂部"android:visibility="gone" /></RelativeLayout>滾動條的問題
setHorizontalScrollBarEnabled(false);//水平不顯示
setVerticalScrollBarEnabled(false); //垂直不顯示
setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);//滾動條在WebView內側顯示
- setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY)//滾動條在WebView外側顯示
設置縮放以及自適應屏幕
WebView 只需要開啟設置相關屬性就可以支持縮放。
縮放自適應屏幕
WebSettings settings = webView.getSettings();// 縮放相關屬性設置settings.setUseWideViewPort(true);//設定支持viewportsettings.setLoadWithOverviewMode(true); //自適應屏幕settings.setBuiltInZoomControls(true);settings.setDisplayZoomControls(false);// 隱藏縮放控件settings.setSupportZoom(true);//設定支持縮放取消縮放控件:
settings.setDisplayZoomControls(false);自行設置初始的縮放比例:
webView.setInitialScale(25);//為25%,最小縮放等級,整個網頁縮放僅對字體進行縮放
settings.setTextZoom(int); 或者 settings.setTextSize(TextSize.LARGER);Android自帶五個可選字體大小的值:SMALLEST(50%),SMALLER(75%),NORMAL(100%),LARGER(150%), LARGEST(200%)。
獲取WebView的Cookie數據
我們都知道Cookie其實只是一個代表用戶唯一標識的字符串,情景一般是: 用戶輸入賬號密碼后,點擊登陸,用戶要拿著這個Cookie去訪問服務器提供的相關服務! 我們可以把cookie的獲取寫到onPageFinsihed的方法中,簡單的可以這樣寫:
@Override public void onPageFinished(WebView view, String url) { CookieManager cookieManager = CookieManager.getInstance();String CookieStr = cookieManager.getCookie(url);Log.e("Cookie", "Cookies = " + CookieStr);super.onPageFinished(view, url); }設置WebView的Cookie數據
我們上面獲取到了Cookie或者通過其他途徑獲得了Cookie,如何為WebView設置Cookie呢?我們可以在需要設置Cookie的地方加入下述代碼:
CookieSyncManager.createInstance(MainActivity.this); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.setCookie(url, cookies); //cookies是要設置的cookie字符串 CookieSyncManager.getInstance().sync();上述代碼需要寫在loadUrl()之前,而且如果設置了Cookie了,盡量別再進行其他的設置 不然可能會無效,建議設置cookie的寫在webView相關設置的最后面~loadUrl()之前!
WebView和JavaScrip交互
這里我們要演示的是通過:HTML -> JS ->Java來完成HTML5端與Android手機間的 互訪。
說明:示例使用到的HTML都是以文件的形式放到assets目錄下,只需通過 loadUrl(“file:///android_asset/~”)即可加載對應的HTML~
核心步驟
- 首先,我們定義一個類,用于將數據暴露出來,JS通過該類暴露的方法(Public)來調用Android!
- 接著,我們在WebView所在頁面Activity,使用下述代碼:
- 然后js或者html中調用name.xxx調用對象里的暴露的方法:
比如:
< input type="button" value="Toast提示" onclick="name.showToast('提示信息');"/>
另外,setJavaScriptEnabled是在Android 4.4以前的系統才有效。
常見示例
HTML通過JS顯示Toast與普通列表的對話框
效果圖
assets/demo1.html
先準備我們的HTML文件,創建好后放到assets目錄下:
<html> <head><title>Js調用Android</title> </head><body> <input type="button" value="Toast提示" onclick="myObj.showToast('JS觸發的Toast');"/> <input type="button" value="列表對話框" onclick="myObj.showDialog();"/> </body> </html>MyObject.java
自定義一個Object對象,js通過該類暴露的方法來調用Android
package com.turing.base.activity.webview.WebView_Js_inter;import android.content.Context; import android.support.v7.app.AlertDialog; import android.webkit.JavascriptInterface; import android.widget.Toast;import com.turing.base.R;/*** MyApp** @author Mr.Yang on 2016-03-24 14:28.* @version 1.0* 自定義一個Object對象,js通過該類暴露的方法來調用Android*/ public class MyObject {private Context context;public MyObject(Context context) {this.context = context;}/*** If you've set your targetSdkVersion to 17 or higher,* you must add the @JavascriptInterface annotation to any method* that you want available to your JavaScript (the method must also be public).* If you do not provide the annotation,* the method is not accessible by your web page* when running on Android 4.2 or higher.** @param name*///將顯示Toast和對話框的方法暴露給JS腳本調用@JavascriptInterfacepublic void showToast(String name) {Toast.makeText(context, name, Toast.LENGTH_SHORT).show();}@JavascriptInterfacepublic void showDialog() {new AlertDialog.Builder(context).setTitle("聯系人列表").setIcon(R.drawable.flag_mark_blue).setItems(new String[]{"111", "222", "333", "444", "555", "666"}, null).setPositiveButton("確定", null).create().show();} }WebViewAndJs01.java
最后在Act中,啟用JavaScript支持,然后通過addJavascriptInterface暴露對象~
package com.turing.base.activity.webview.WebView_Js_inter;import android.annotation.SuppressLint; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.WebSettings; import android.webkit.WebView;import com.turing.base.R;/*** 啟用JavaScript支持,然后通過addJavascriptInterface暴露對象~*/ public class WebViewAndJs01 extends AppCompatActivity {private WebView webView ;@SuppressLint("JavascriptInterface")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view_and_js01);webView = (WebView) findViewById(R.id.id_webview_JS);//加載assets目錄下的html文件webView.loadUrl("file:///android_asset/demo1.html");WebSettings webSettings = webView.getSettings();//①設置WebView允許調用jswebSettings.setJavaScriptEnabled(true);webSettings.setDefaultTextEncodingName("UTF-8");//②將object對象暴露給Js,調用addjavascriptInterfacewebView.addJavascriptInterface(new MyObject(WebViewAndJs01.this), "myObj");} }activity_web_view_and_js01.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><WebView android:id="@+id/id_webview_JS"android:layout_width="match_parent"android:layout_height="match_parent"/></RelativeLayout>HTML通過JS調用三種不同的對話框
效果圖
assets/demo2.html
先往assets目錄下塞一個html文件: demo2.html:
<html> <head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"<title>測試Js的三種不同對話框</title><script language="JavaScript">function alertFun(){alert("Alert警告對話框!");}function confirmFun(){if(confirm("訪問百度?")){location.href = "http://www.baidu.com";}else alert("取消訪問!");}function promptFun(){var word = prompt("Prompt對話框","請輸入點什么...:");if(word){alert("你輸入了:"+word)}else{alert("呵呵,你什么都沒寫!");}}</script> </head><body> <p>三種對話框的使用</p><p>Alert對話框</p><p><input type="submit" name="Submit1" value="展示1" onclick="alertFun()"/> </p><p>Confirm對話框</p><p><input type="submit" name="Submit2" value="展示2" onclick="confirmFun()"/> </p><p>Prompt對話框</p><p><input type="submit" name="Submit3" value="展示3" onclick="promptFun()"/> </p> </body> </html>WebviewJS02.java
package com.turing.base.activity.webview.WebView_Js_inter;import android.content.DialogInterface; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.webkit.JsPromptResult; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.EditText; import android.widget.TextView;import com.turing.base.R;/*** HTML通過JS調用三種不同的對話框*/ public class WebviewJS02 extends AppCompatActivity {private WebView wView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview_js02);wView = (WebView) findViewById(R.id.wView);//獲得WebSetting對象,支持js腳本,可訪問文件,支持縮放,以及編碼方式WebSettings webSettings = wView.getSettings();webSettings.setJavaScriptEnabled(true);webSettings.setAllowFileAccess(true);webSettings.setBuiltInZoomControls(true);webSettings.setDefaultTextEncodingName("UTF-8");//設置WebChromeClient,處理網頁中的各種js事件wView.setWebChromeClient(new MyWebChromeClient());wView.loadUrl("file:///android_asset/demo2.html");}//這里需要自定義一個類實現WebChromeClient類,并重寫三種不同對話框的處理方法//分別重寫onJsAlert,onJsConfirm,onJsPrompt方法class MyWebChromeClient extends WebChromeClient {@Overridepublic boolean onJsAlert(WebView view, String url, String message,final JsResult result) {//創建一個Builder來顯示網頁中的對話框new AlertDialog.Builder(WebviewJS02.this).setTitle("Alert對話框").setMessage(message).setPositiveButton("確定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {result.confirm();}}).setCancelable(false).show();return true;}@Overridepublic boolean onJsConfirm(WebView view, String url, String message,final JsResult result) {new AlertDialog.Builder(WebviewJS02.this).setTitle("Confirm對話框").setMessage(message).setPositiveButton("確定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {result.confirm();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {result.cancel();}}).setCancelable(false).show();return true;}@Overridepublic boolean onJsPrompt(WebView view, String url, String message,String defaultValue, final JsPromptResult result) {//①獲得一個LayoutInflater對象factory,加載指定布局成相應對象final LayoutInflater inflater = LayoutInflater.from(WebviewJS02.this);final View myview = inflater.inflate(R.layout.prompt_view, null);//設置TextView對應網頁中的提示信息,edit設置來自于網頁的默認文字((TextView) myview.findViewById(R.id.text)).setText(message);((EditText) myview.findViewById(R.id.edit)).setText(defaultValue);//定義對話框上的確定按鈕new AlertDialog.Builder(WebviewJS02.this).setTitle("Prompt對話框").setView(myview).setPositiveButton("確定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//單擊確定后取得輸入的值,傳給網頁處理String value = ((EditText) myview.findViewById(R.id.edit)).getText().toString();result.confirm(value);}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {result.cancel();}}).show();return true;}} }activity_webview_js02.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><WebView android:id="@+id/wView"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="5dp" /></RelativeLayout>prompt_view.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextView android:id="@+id/text"android:layout_width="match_parent"android:layout_height="wrap_content" /><EditText android:id="@+id/edit"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollHorizontally="true"android:selectAllOnFocus="true" /></LinearLayout>HTML通過JS讀取Android聯系人并顯示
思路
實現思路:通過js讀取Android手機中聯系列表,然后顯示到HTML中 當我們點擊某個電話號碼時,會直接跳轉到撥號頁面 。
實現關鍵: 利用onload()在網頁加載的時候加載相應的js腳本,而js腳本中定義的一個函數是 取出傳遞過來的對象,獲取里面的數據,通過for循環以單元行的形式打印出來!
assets/demo3.html
<html> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>顯示獲取的聯系人列表</title><script language="JavaScript">function show(jsondata) { //將傳遞過來的Json轉換為對象 var jsonobjs = eval(jsondata); //獲取下面定義的表格 var table = document.getElementById("PersonTable"); //遍歷上面創建的Json對象,將每個對象添加為 //表格中的一行,而它的每個屬性作為一列 for(var i = 0;i < jsonobjs.length;i++) { //添加一行,三個單元格: var tr = table.insertRow(table.rows.length); var td1 = tr.insertCell(0); var td2 = tr.insertCell(1); td2.align = "center"; var td3 = tr.insertCell(2); //設置單元格的內容和屬性 //其中innerHTML為設置或者獲取位于對象起始和結束標簽內的HTML //jsonobjs[i]為對象數組中的第i個對象 td1.innerHTML = jsonobjs[i].id; td2.innerHTML = jsonobjs[i].name; //為現實的內容添加超鏈接,超鏈接會調用Java代碼中的 //call方法并且把內容作為參數傳遞過去 td3.innerHTML = "<a href = 'javascript:sharp.call(\""+jsonobjs[i].phone + "\")'>" +jsonobjs[i].phone + "</a>";; } } </script> </head><!-- onload指定該頁面被加載時調用的方法,這里調用的是Java代碼中的contactlist方法--> <body style="margin:0px; background-color:#FFFFFF; color:#000000;" onload = "javascript:sharp.contactlist()"> <!--定義一個表格--> <table border = "0" width = "100%" id = "PersonTable" cellspacing = "0"><tr><td width = "15%">用戶id</td><td align = "center">姓名</td><td width = "15%">號碼</td></tr> </table> </body> </html>業務類Contact.java
package com.turing.base.activity.webview.WebView_Js_inter;/*** MyApp** @author Mr.Yang on 2016-03-24 15:24.* @version 1.0* @desc*/ public class Contact {private String id;private String name;private String phone;public Contact() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Overridepublic String toString() {return this.id + "~" + this.name + "~" + this.phone;} }WebViewReadContactsAct.java
package com.turing.base.activity.webview.WebView_Js_inter;import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.webkit.JavascriptInterface; import android.webkit.WebView;import com.turing.base.R;import org.json.JSONArray; import org.json.JSONObject;import java.util.ArrayList; import java.util.List;/*** 讀取聯系人** 該代碼實現的是通過js讀取Android手機中聯系列表,* 然后顯示到HTML中 當我們點擊某個電話號碼時,會直接跳轉到撥號頁面* 實現關鍵: 利用onload()在網頁加載的時候加載相應的js腳本,* 而js腳本中定義的一個函數是 取出傳遞過來的對象,* 獲取里面的數據,通過for循環以單元行的形式打印出來!*/ public class WebViewReadContactsAct extends AppCompatActivity {private WebView wView;@SuppressLint("JavascriptInterface")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view_read_contacts);//設置WebView的相關設置,依次是://支持js,不保存表單,不保存密碼,不支持縮放//同時綁定Java對象wView = (WebView) findViewById(R.id.wView);wView.getSettings().setJavaScriptEnabled(true);wView.getSettings().setSaveFormData(false);wView.getSettings().setSavePassword(false);wView.getSettings().setSupportZoom(false);wView.getSettings().setDefaultTextEncodingName("UTF-8");wView.addJavascriptInterface(new SharpJS(), "sharp");wView.loadUrl("file:///android_asset/demo3.html");}//自定義一個Js的業務類,傳遞給JS的對象就是這個,調用時直接javascript:sharp.contactlist()public class SharpJS {/*** 所有的WebView方法都應該在同一個線程程中調用*/@JavascriptInterfacepublic void contactlist() {wView.post(new Runnable() {@Overridepublic void run() {try {System.out.println("contactlist()方法執行了!");String json = buildJson(getContacts());wView.loadUrl("javascript:show('" + json + "')");} catch (Exception e) {System.out.println("設置數據失敗" + e);}}});}@JavascriptInterfacepublic void call(String phone) {System.out.println("call()方法執行了!");Intent it = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));startActivity(it);}}//將獲取到的聯系人集合寫入到JsonObject對象中,再添加到JsonArray數組中public String buildJson(List<Contact> contacts) throws Exception {JSONArray array = new JSONArray();for (Contact contact : contacts) {JSONObject jsonObject = new JSONObject();jsonObject.put("id", contact.getId());jsonObject.put("name", contact.getName());jsonObject.put("phone", contact.getPhone());array.put(jsonObject);}return array.toString();}//定義一個獲取聯系人的方法,返回的是List<Contact>的數據public List<Contact> getContacts() {List<Contact> Contacts = new ArrayList<Contact>();//①查詢raw_contacts表獲得聯系人的idContentResolver resolver = getContentResolver();Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;//查詢聯系人數據Cursor cursor = resolver.query(uri, null, null, null, null);while (cursor.moveToNext()) {Contact contact = new Contact();//獲取聯系人姓名,手機號碼contact.setId(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));contact.setName(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));contact.setPhone(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));Contacts.add(contact);}cursor.close();return Contacts;} }activity_web_view_read_contacts.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.turing.base.activity.webview.WebView_Js_inter.WebViewReadContactsAct"><WebView android:id="@+id/wView"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="5dp" /> </RelativeLayout>Android 4.4后WebView的一些注意事項
從Android 4.4開始,Android中的WebView不再是基于WebKit的,而是開始基于Chromium,這個改變 使得WebView的性能大幅提升,并且對HTML5,CSS,JavaScript有了更好的支持!
雖然chromium完全取代了以前的WebKit for Android,但Android WebView的API接口并沒有變, 與老的版本完全兼容。這樣帶來的好處是基于WebView構建的APP,無需做任何修改, 就能享受chromium內核的高效與強大。
對于4.4后的WebView,我們需要注意下下面這些問題:
多線程
如果你在子線程中調用WebView的相關方法,而不在UI線程,則可能會出現無法預料的錯誤。 所以,當你的程序中需要用到多線程時候,也請使用runOnUiThread()方法來保證你關于 WebView的操作是在UI線程中進行的:
runOnUiThread(newRunnable(){ @Override publicvoid run(){// Code for WebView goes here} });線程阻塞
永遠不要阻塞UI線程,這是開發Android程序的一個真理。雖然是真理,我們卻往往不自覺的 犯一些錯誤違背它,一個開發中常犯的錯誤就是:在UI線程中去等待JavaScript 的回調。 例如:
// This code is BAD and will block the UI thread webView.loadUrl("javascript:fn()"); while(result ==null) { Thread.sleep(100); }千萬不要這樣做,Android 4.4中,提供了新的Api來做這件事情。 evaluateJavascript() 就是專門來異步執行JavaScript代碼的。
evaluateJavascript() 方法
專門用于異步調用JavaScript方法,并且能夠得到一個回調結果。
mWebView.evaluateJavascript(script, new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//TODO} });處理WebView中url的跳轉
新版WebView對于自定義scheme的url跳轉,新增了更為嚴格的限制條件。 當你實現了 shouldOverrideUrlLoading() 或 shouldInterceptRequest() 回調,WebView 也只會在跳轉url是合法Url時才會跳轉。 例如,如果你使用這樣一個url :
<a href="showProfile">Show Profile</a>shouldOverrideUrlLoading() 將不會被調用。
正確的使用方式是:
<a href="example-app:showProfile">Show Profile</a>對應的檢測Url跳轉的方式:
/ The URL scheme should be non-hierarchical (no trailing slashes)privatestaticfinalString APP_SCHEME ="example-app:";@Override publicboolean shouldOverrideUrlLoading(WebView view,String url){if(url.startsWith(APP_SCHEME)){urlData =URLDecoder.decode(url.substring(APP_SCHEME.length()),"UTF-8");respondToData(urlData);returntrue;}returnfalse; }當然,也可以這樣使用:
webView.loadDataWithBaseURL("example-app://example.co.uk/", HTML_DATA,null,"UTF-8",null);UserAgent變化
如果你的App對應的服務端程序,會根據客戶端傳來的UserAgent來做不同的事情,那么你需要注意 的是,新版本的WebView中,UserAgent有了些微妙的改變:
Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16H) AppleWebKit/537.36(KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36使用getDefaultUserAgent()方法可以獲取默認的UserAgent,也可以通過:
mWebView.getSettings().setUserAgentString(ua); mWebView.getSettings().getUserAgentString();來設置和獲取自定義的UserAgent。
使用addJavascriptInterface()的注意事項
從Android4.2開始。 只有添加 @JavascriptInterface 聲明的Java方法才可以被JavaScript調用, 例如:
class JsObject {@JavascriptInterfacepublic String toString() { return "injectedObject"; } }webView.addJavascriptInterface(new JsObject(), "injectedObject"); webView.loadData("", "text/html", null); webView.loadUrl("javascript:alert(injectedObject.toString())");Remote Debugging
新版的WebView還提供了一個很厲害的功能:使用Chrome來調試你運行在WebView中的程序 具體可以看:remote-debugging
WebView文件下載
調用其它瀏覽器下載文件
運行圖
Code
布局文件,只有一個webview,就不貼了,下面看下主Act
ProgressDialog還不嚴謹,粗略演示下~
如果存在多個應用可以下載,系統會彈出選擇框
自己寫線程下載文件
當然,你可能不想把下載文件放到默認路徑下,或者想自己定義文件名等等,你都可以自己來寫 一個線程來下載文件,實現示例代碼如下:
DownLoadThread.java
package com.turing.base.activity.webview.WebView_Download;import android.os.Environment;import com.apkfuns.logutils.LogUtils;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL;/*** MyApp** @author Mr.Yang on 2016-03-24 17:47.* @version 1.0* @desc*/ public class DownLoadThread implements Runnable {private String url;public DownLoadThread(String url) {this.url = url;}/*** 使用HttpURLConnection下載*/@Overridepublic void run() {// 處理下載業務邏輯LogUtils.e( "開始下載~~~~~" + url);InputStream in = null;FileOutputStream fout = null;try {// 實例化URlURL httpUrl = new URL(url);HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();conn.setDoInput(true);conn.setDoOutput(true);in = conn.getInputStream();File downloadFile, sdFile;if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {downloadFile = Environment.getExternalStorageDirectory();sdFile = new File(downloadFile, "dowload.apk");fout = new FileOutputStream(sdFile);}else{LogUtils.e("SD卡不存在或者不可讀寫");}// 緩沖區byte[] buffer = new byte[1024];int len;// 循環讀取while ((len = in.read(buffer)) != -1) {fout.write(buffer, 0, len);}LogUtils.e("下載完畢~~~~");} catch (Exception e) {e.printStackTrace();LogUtils.e("下載異常~~~~");} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}if (fout != null) {try {fout.close();} catch (IOException e) {e.printStackTrace();}}}} }WebViewDownLoadWithSelfThread.java
package com.turing.base.activity.webview.WebView_Download;import android.annotation.TargetApi; import android.app.ProgressDialog; import android.content.DialogInterface; import android.graphics.Bitmap; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.DownloadListener; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient;import com.apkfuns.logutils.LogUtils; import com.turing.base.R;public class WebViewDownLoadWithSelfThread extends AppCompatActivity {private WebView webView;@TargetApi(Build.VERSION_CODES.HONEYCOMB)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view_down_load_with_self_thread);webView = (WebView) findViewById(R.id.id_webview);webView.setWebViewClient(new WebViewClient() {// 設置WebView點擊打開的網頁在當前界面顯示,而不是跳到新的瀏覽器中@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {LogUtils.e("onPageStarted");showProgressDialog();}@Overridepublic void onPageFinished(WebView view, String url) {LogUtils.e("onPageFinished");closeProgressDialog();}@Overridepublic void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {super.onReceivedError(view, request, error);LogUtils.e("onReceivedError");closeProgressDialog();}});WebSettings settings = webView.getSettings();// 允許執行JS腳本settings.setJavaScriptEnabled(true);// 縮放相關屬性設置settings.setUseWideViewPort(true);//設定支持viewportsettings.setLoadWithOverviewMode(true); //自適應屏幕settings.setBuiltInZoomControls(true);settings.setDisplayZoomControls(false);// 隱藏縮放控件settings.setSupportZoom(true);//設定支持縮放// 載入URLwebView.loadUrl("http://www.csdn.net/app/");// 然后,找到下載的地方,這個時候點擊下載,調用自己寫的下載程序//WebView默認沒有開啟文件下載的功能,// 如果要實現文件下載的功能,需要設置WebView的DownloadListenerwebView.setDownloadListener(new DownloadListener() {@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {// 自己實現的下載邏輯線程new Thread(new DownLoadThread(url)).start();}});}/*** 載入前加載*/ProgressDialog mDialog;private void showProgressDialog() {mDialog = new ProgressDialog(this);mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);//設置風格為圓形進度條mDialog.setMessage("正在加載 ,請等待...");mDialog.setIndeterminate(false);//設置進度條是否為不明確mDialog.setCancelable(true);//設置進度條是否可以按退回鍵取消 默認truemDialog.setCanceledOnTouchOutside(false);//設置在點擊Dialog外是否取消Dialog進度條 默認truemDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {@Overridepublic void onDismiss(DialogInterface dialog) {mDialog = null;}});mDialog.show();}private void closeProgressDialog() {mDialog.dismiss();mDialog = null;} }清單文件配置權限
<uses-permission android:name="android.permission.INTERNET"/> <!-- 在SDCard中創建與刪除文件權限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard寫入數據權限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>WebView緩存問題
現在很多門戶類信息網站,信息閱讀類的APP,很多 都是直接嵌套一個WebView用來顯示相關資訊的,這可能就涉及到了WebView的緩存了!
所謂的頁面緩存 就是指:保存加載一個網頁時所需的HTML,JS,CSS等頁面相關的數據以及其他資源,當沒網的時候或者 網絡狀態較差的時候,加載本地保存好的相關數據!而實現這個緩存的方式有兩種,一種是后臺寫一個 下載的Service,將文章相關的數據按自己的需求下載到數據庫或者保存到相應文件夾中,然后下次加載 對應URL前先判斷是否存在本地緩存,如果存在優先加載本地緩存,不存在則執行聯網請求,同時緩存 相關資源,典型的如舊版本的36Kr,在進去后會先離線文章,然后再顯示!
當然,這里要講解的不是 這種自己寫邏輯的方式,而是通過WebView本身自帶的緩存功能來緩存頁面,這種方式使用起來非常 簡單,我們只需為WebView設置開啟相關功能,以及設置數據庫的緩存路徑即可完成緩存!具體的 實現我們下面一一道來~
緩存的分類
首先要說的一點是緩存的分類,我們緩存的數據分為:頁面緩存和數據緩存
- 頁面緩存:加載一個網頁時的html、JS、CSS等頁面或者資源數據,這些緩存資源是由于瀏覽器 的行為而產生,開發者只能通過配置HTTP響應頭影響瀏覽器的行為才能間接地影響到這些緩存數據。
而緩存的索引放在:/data/data/<包名>/databases
對應的文件放在:/data/data/package_name/cache/webviewCacheChromunm下 - 數據緩存:分為AppCache和DOM Storage兩種 我們開發者可以自行控制的就是這些緩存資源,
AppCache:我們能夠有選擇的緩沖web瀏覽器中所有的東西,從頁面、圖片到腳本、css等等。 尤其在涉及到應用于網站的多個頁面上的CSS和JavaScript文件的時候非常有用。其大小目前通常是5M。 在Android上需要手動開啟(setAppCacheEnabled),并設置路徑(setAppCachePath)和容量 (setAppCacheMaxSize),而Android中使用ApplicationCache.db來保存AppCache數據!
DOM Storage:存儲一些簡單的用key/value對即可解決的數據,根據作用范圍的不同,有Session Storage和Local Storage兩種,分別用于會話級別的存儲(頁面關閉即消失)和本地化存儲(除非主動 刪除,否則數據永遠不會過期)在Android中可以手動開啟DOM Storage(setDomStorageEnabled), 設置存儲路徑(setDatabasePath)Android中Webkit會為DOMStorage產生兩個文件(my_path/localstorage/http_blog.csdn.net_0.localstorage和my_path/Databases.db)
另外還要說下幾種緩存的模式:
- LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據
- LOAD_DEFAULT: 根據cache-control決定是否從網絡上取數據。
- LOAD_CACHE_NORMAL: API level 17中已經廢棄, 從API level 11開始作用同LOAD_DEFAULT模式
- LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據.
- LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。
總結:根據以上兩種模式,建議緩存策略為,判斷是否有網絡,有的話,使用LOAD_DEFAULT, 無網絡時,使用LOAD_CACHE_ELSE_NETWORK。
http://www.runoob.com/w3cnote/android-tutorial-webview-cache.html
為WebView開啟緩存功能
流程解析: 1.進入頁面后默認加載url,然后隨便點擊一個鏈接跳到第二個頁面,退出APP 2.關閉wifi以及移動網絡,然后重新進入,發現無網絡的情況下,頁面還是加載了, 打開第一個鏈接也可以加載,打開其他鏈接就發現找不到網頁! 3.點擊清除緩存,把應用關閉,重新進入,發現頁面已經打不開!
package com.turing.base.activity.webview.WebView_Cache;import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button;import com.apkfuns.logutils.LogUtils; import com.turing.base.R;/*** 開啟緩存的功能,以及設置緩存模式以及緩存的數據的路徑*/ public class WebViewCacheAct extends AppCompatActivity {private WebView wView;private Button btn_clear_cache;private Button btn_refresh;private static final String APP_CACHE_DIRNAME = "/webcache"; // web緩存目錄private static final String URL = "http://blog.csdn.net/yangshangwei";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_web_view_cache);wView = (WebView) findViewById(R.id.wView);btn_clear_cache = (Button) findViewById(R.id.btn_clear_cache);btn_refresh = (Button) findViewById(R.id.btn_refresh);wView.loadUrl(URL);wView.setWebViewClient(new WebViewClient() {//設置在webView點擊打開的新網頁在當前界面顯示,而不跳轉到新的瀏覽器中@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});WebSettings settings = wView.getSettings();settings.setJavaScriptEnabled(true);//設置緩存模式settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);// 開啟DOM storage API 功能settings.setDomStorageEnabled(true);// 開啟database storage API功能settings.setDatabaseEnabled(true);String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACHE_DIRNAME;LogUtils.e("cachePath:"+ cacheDirPath);// 設置數據庫緩存路徑settings.setAppCachePath(cacheDirPath);settings.setAppCacheEnabled(true);LogUtils.e("databasepath:"+ settings.getDatabasePath());// 清除緩存btn_clear_cache.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {wView.clearCache(true);}});// 刷新btn_refresh.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {wView.reload();}});}//重寫回退按鈕的點擊事件@Overridepublic void onBackPressed() {if(wView.canGoBack()){wView.goBack();}else{super.onBackPressed();}} }刪除WebView的緩存數據
上面的示例,我們通過調用WebView的clearCache(true)方法,已經實現了對緩存的刪除! 除了這種方法外,還有下述方法:
- setting.setCacheMode(WebSettings.LOAD_NO_CACHE);
- deleteDatabase(“WebView.db”);和deleteDatabase(“WebViewCache.db”);
- webView.clearHistory();
- webView.clearFormData();
- getCacheDir().delete();
- 手動寫delete方法,循環迭代刪除緩存文件夾!
當然,前面也說,我們能這直接操作的只是數據部分,而頁面緩存是由于瀏覽器 的行為而產生,我們只能通過配置HTTP響應頭影響瀏覽器的行為才能間接地影響到 這些緩存數據。所以上述的方法僅僅是刪除的數據部分的緩存!
WebView處理網頁返回的錯誤碼信息
假如你們公司是做HTML5端的移動APP的,就是通過WebView來顯示網頁的,假如你訪問的網頁 不存在,或者其他錯誤,報404,401,403,30X等錯誤的狀態碼,如果直接彈出WebView默認的錯誤 提示頁面,可能顯得不那么友好,我們可以重寫WebViewClient的onReceivedError()方法來實現我們 想要的效果,一般的做法有兩種,一種是:我們自己在assets目錄下創建一個用于顯示錯誤信息的 HTML頁面,當發生錯誤,即onReceivedError()被調用的時候我們調用webView的loadUrl跳到我們 的錯誤頁面,比如:wView.loadUrl(“file:///android_asset/error.html”);!又或者我們另外寫 一個布局或者直接一個大大的圖片,平時設置為不可見,當頁面錯誤時,讓該布局或者圖片可見!
頁面錯誤,加載自定義網頁
wView.setWebViewClient(new WebViewClient() { //設置在webView點擊打開的新網頁在當前界面顯示,而不跳轉到新的瀏覽器中 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true; }@Override public void onReceivedError(WebView view, int errorCode, String description,String failingUrl) {super.onReceivedError(view, errorCode, description, failingUrl);wView.loadUrl("file:///android_asset/error.html");} });頁面錯誤,顯示相應的View
public class MainActivity extends AppCompatActivity implements View.OnClickListener{private WebView wView;private ImageView img_error_back;private Button btn_refresh;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);wView = (WebView) findViewById(R.id.wView);img_error_back = (ImageView) findViewById(R.id.img_error_back);btn_refresh = (Button) findViewById(R.id.btn_refresh);wView.loadUrl("http://www.baidu.com");wView.setWebViewClient(new WebViewClient() {//設置在webView點擊打開的新網頁在當前界面顯示,而不跳轉到新的瀏覽器中@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}@Overridepublic void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {super.onReceivedError(view, errorCode, description, failingUrl);wView.setVisibility(View.GONE);img_error_back.setVisibility(View.VISIBLE);}});btn_refresh.setOnClickListener(this);}@Overridepublic void onClick(View v) {wView.loadUrl("http://www.baidu.com");img_error_back.setVisibility(View.GONE);wView.setVisibility(View.VISIBLE);} }除此之外:
Android 調用js有個漏洞:詳情請查看原作者博文:
http://blog.csdn.net/leehong2005/article/details/11808557
還有簡書上的一片博文,可以參考下
http://www.jianshu.com/p/3fcf8ba18d7f
再此僅作為記錄。
總結
以上是生活随笔為你收集整理的WebView完全解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android开发实用工具汇总-持续更新
- 下一篇: Android系统服务