android webview 使用以及一些常见的异常处理
android中的提供webview控件,可以方便开发人员是自己的应用嵌入网页浏览功能,但实际开发中却会遇到 一些问题,这个稍后会介绍到,
效果图:
先来看个实例:
- public class MainActivity extends Activity {
- final String COMPANY_WEB="http://www.csdn.net";
- private WebView mWebView;
- @Override
- protected 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{
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- super.onPageStarted(view, url, favicon);
- }
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- }
- @Override
- public 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);
- }
- }
- @Override
- public 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>();
- @Override
- protected 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{
- @Override
- public 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();
- //错误<strong>处理</strong>
- 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浏览器中那样跳出一个风险提示框
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler,
- SslError error) {
- //忽略证书的错误继续Load页面内容
- handler.proceed();
- //handler.cancel(); // Android默认的<strong>处理</strong>方式
- //handleMessage(Message msg); // 进行其他<strong>处理</strong>
- // super.onReceivedSslError(view, handler, error);
- }
- @Override
- public 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);
- }
- @Override
- public 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);
- }
- @Override
- public 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;
- @Override
- public void onPause() {
- super.onPause();
- if (mWebView != null) {
- mWebView.pauseTimers();
- mWebView.onPause();
- this.pause=true;
- }
- }
- @Override
- public void onResume() {
- super.onResume();
- if (mWebView != null&&pause) {
- mWebView.resumeTimers();
- mWebView.onResume();
- this.pause=false;
- }
- }
- @Override
- public 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" />
经过代码优化后,访问速度明显提升,部分错误得到 处理,但是还是会有 异常 处理不了,如果谁有好的错误 处理方法,希望留言讨论,大家一起进步。
好了就先说到这里吧!
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐