android中的提供webview控制項,可以方便開發人員是自己的應用嵌入網頁瀏覽功能,但實際開發中卻會遇到一些問題,這個稍後會介紹到,
:
先來看個執行個體:
public class MainActivity extends Activity {final String COMPANY_WEB="http://www.csdn.net";private WebView mWebView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mWebView = (WebView) findViewById(R.id.webview);setWebView();}private void setWebView(){WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setAllowFileAccess(true); webSettings.setBuiltInZoomControls(true); webSettings.setPluginsEnabled(true);mWebView.setWebViewClient(new MonitorWebClient());mWebView.loadUrl(COMPANY_WEB);}private class MonitorWebClient extends WebViewClient{@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);}@Overridepublic boolean shouldOverrideUrlLoading(WebView view, final String url) {String website=Uri.parse(url).getHost();if (COMPANY_WEB.equals(website)) { // This is my web site, so do not override; let my WebView load the page return false; }else{ view.loadUrl(url); return true; }//return super.shouldOverrideUrlLoading(view, url);}}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { mWebView.goBack(); return true; } return super.onKeyDown(keyCode, event);}}
相關許可權:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
ok,測試了一下相關連結也可以出現正常訪問,以上是以csdn網站為例,如果將網站換成http://www.qq.com開始也沒有問題,點擊導覽列也可以正常訪問,再點擊圖片串連就會出現 eventhub.removemessages(int what = 107) is not supported before the webviewcore is set up異常資訊,有人說是沒有以http://開頭,這個也試了一下,沒有解決問題,期待有人能解決。回過頭來在首頁點擊相關新聞連結後會發現出現空白頁無法正常訪問,後來研究發現這個和網站結構有關係,看來webview並不能完全實現瀏覽器功能。
接下來就是簡單的異常處理了,主要就是重寫WebViewClient類中的onReceivedError()方法和onReceivedSslError()方法來進行處理了。
說完異常簡單處理後再來說說提高網站的訪問速度,尤其是帶有大量的flash,swf動畫和各種css樣式功能,這個時候我們就應該使用緩衝了,適當的設定緩衝大小以及合適的模式來進行最佳化了,webview有兩種模式可設定如下:
1,LOAD_DEFAULT,根據cache-control決定是否從網路上取資料。
2,LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否到期,或者no-cache,都使用緩衝中的資料。
如:m.taobao.com的cache-control為no-cache,在模式LOAD_DEFAULT下,無論如何都會從網路上取資料,如果沒有網路,就會出現錯誤頁面;在LOAD_CACHE_ELSE_NETWORK模式下,無論是否有網路,只要開啟過一次,都使用緩衝。
m.sina.com.cn的cache-control為max-age=60,在兩種模式下都使用本機快取資料。
總結:根據以上兩種模式,建議緩衝策略為,判斷是否有網路,有的話,使用LOAD_DEFAULT,無網路時,使用LOAD_CACHE_ELSE_NETWORK。
好說的也差不多了,來看一下最佳化後的代碼:
public class MainActivity extends Activity {final String COMPANY_WEB="http://www.deczh.com/";private WebView mWebView;private Context activity;//private ProgressDialog progressDialog;//history web site//private Stack<String> webHistory=new Stack<String>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mWebView = (WebView) findViewById(R.id.webview);setWebView();activity=this;mHandler.sendEmptyMessageDelayed(0, 1000);}private void setWebView(){WebSettings webSettings = mWebView.getSettings(); //java script webSettings.setJavaScriptEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // access Assets and resources webSettings.setAllowFileAccess(true); //zoom page webSettings.setBuiltInZoomControls(true); webSettings.setPluginsEnabled(true); //set xml dom cache webSettings.setDomStorageEnabled(true); //提高渲染的優先順序 webSettings.setRenderPriority(RenderPriority.HIGH); //set cache String appCachePath = getDir("netCache", Context.MODE_PRIVATE).getAbsolutePath(); webSettings.setAppCacheEnabled(true); webSettings.setAppCachePath(appCachePath); webSettings.setAppCacheMaxSize(1024*1024*5); webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);mWebView.setWebViewClient(new MonitorWebClient());mWebView.setWebChromeClient(new AppCacheWebChromeClient());}private class MonitorWebClient extends WebViewClient{@Overridepublic void onReceivedError(WebView view, int errorCode,String description, String failingUrl) {//錯誤提示Toast toast = Toast.makeText(getBaseContext(), "Oh no! " + description, Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0); toast.show(); //錯誤處理 try { mWebView.stopLoading(); } catch (Exception e) { } try { mWebView.clearView(); } catch (Exception e) { } if (mWebView.canGoBack()) { mWebView.goBack(); }//super.onReceivedError(view, errorCode, description, failingUrl);}//當load有ssl層的https頁面時,如果這個網站的安全性憑證在Android無法得到認證,WebView就會變成一個空白頁,而並不會像PC瀏覽器中那樣跳出一個風險提示框@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error) {//忽略認證的錯誤繼續Load頁面內容 handler.proceed();//handler.cancel(); // Android預設的處理方式 //handleMessage(Message msg); // 進行其他處理//super.onReceivedSslError(view, handler, error);}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) { /*if (progressDialog == null) { // If no progress dialog, make one and set message progressDialog = new ProgressDialog(activity); progressDialog.setMessage("Loading please wait..."); progressDialog.show(); // Hide the webview while loading mWebView.setEnabled(false); }*///super.onPageStarted(view, url, favicon);}@Overridepublic void onPageFinished(WebView view, String url) { /* if (progressDialog != null&&progressDialog.isShowing()) { progressDialog.dismiss(); progressDialog = null; mWebView.setEnabled(true); }*/ /*if(!webHistory.contains(url)) webHistory.push(url);*///super.onPageFinished(view, url);}@Overridepublic boolean shouldOverrideUrlLoading(WebView view, final String url) {Log.e(getClass().getSimpleName(), "website= "+url);//String website=Uri.parse(url).getHost();String processUrl=url;if(!processUrl.startsWith("http://"))processUrl="http://"+processUrl;if (COMPANY_WEB.equals(url)) { // This is my web site, so do not override; let my WebView load the page return false; } else{ view.loadUrl(processUrl); return true; }// return super.shouldOverrideUrlLoading(view, url);}} private class AppCacheWebChromeClient extends WebChromeClient { @Override public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { // Log.e(APP_CACHE, "onReachedMaxAppCacheSize reached, increasing space: " + spaceNeeded); quotaUpdater.updateQuota(spaceNeeded * 2); } } private boolean pause=false;@Overridepublic void onPause() {super.onPause();if (mWebView != null) {mWebView.pauseTimers();mWebView.onPause();this.pause=true;}}@Overridepublic void onResume() {super.onResume();if (mWebView != null&&pause) {mWebView.resumeTimers();mWebView.onResume();this.pause=false;}}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()){ mWebView.goBack(); return true; } return super.onKeyDown(keyCode, event);}}
相關許可權:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
經過代碼最佳化後,訪問速度明顯提升,部分錯誤得到處理,但是還是會有異常處理不了,如果誰有好的錯誤處理方法,希望留言討論,大家一起進步。
好了就先說到這裡吧!