Android WebView开发

在移动端App的开发中,WebView的使用越来越多,尤其是HTML5兴起,话不多说,边学边记录。

老规矩,先来个搞笑段子:

今天路过一个算命摊位,算命老爷子自己给自己算了一卦,一看结果,下下签,啥也不说,收摊走人。

两分钟,城管来了!这TMD才是大师啊~


一:基本使用

WebView就是一个基本的控件,可以在layout文件中使用

<WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

因为要房访问网络,所以manifest中必须要加uses-permission

<uses-permission android:name="android.permission.INTERNET"/>
activity中即可获得webview的引用,同时load一个网址

webview = (WebView) findViewById(R.id.webView);
webview.loadUrl("http://www.baidu.com/");
启动应用后,自动的打开了系统内置的浏览器,解决这个问题需要为webview设置 WebViewClient,并重写方法

webView.loadUrl("http://www.baidu.com");
webview.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
若自己定义了一个页面加载进度的progressbar,需要展示给用户的时候,可以通过如下方式获取webview内页面的加载进度

webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                //get the newProgress and refresh progress bar
            }
        });
每个页面,都有一个标题,比如www.baidu.com这个页面的title即“百度一下,你就知道”,那么如何知道当前webview正在加载的页面的title呢

webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onReceivedTitle(WebView view, String title) {
                titleview.setText(title);//a textview
            }
        });


二:下载文件

通常webview渲染的界面中含有可以下载文件的链接,点击该链接后,应该开始执行下载的操作并保存文件到本地中。webview来下载页面中的文件通常有两种方式:

1. 自己通过一个线程写java io的代码来下载和保存文件(可控性好)

2. 调用系统download的模块(代码简单)

方法一:

首先要写一个下载并保存文件的线程类

public class HttpThread extends Thread {
  private String mUrl;
  public HttpThread(String mUrl) {
    this.mUrl = mUrl;
  }
  @Override
  public void run() {
    URL url;
    try {
      url = new URL(mUrl);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setDoInput(true);
      conn.setDoOutput(true);
      InputStream in = conn.getInputStream();
      File downloadFile;
      File sdFile;
      FileOutputStream out = null;
      if(Environment.getExternalStorageState().equals(Environment.MEDIA_UNMOUNTED)){
        downloadFile = Environment.getExternalStorageDirectory();
        sdFile = new File(downloadFile, "test.file");
        out = new FileOutputStream(sdFile);
      }
      //buffer 4k
      byte[] buffer = new byte[1024 * 4];
      int len = 0;
      while((len = in.read(buffer)) != -1){
        if(out != null)
          out.write(buffer, 0, len);
      }
      //close resource
      if(out != null)
        out.close();
      if(in != null){
        in.close();
      }
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
然后要实现一个DownloadListener接口,这个接口实现方法OnDownloadStart(),当用户点击一个可以下载的链接时,该回调方法被调用同时传进来该链接的URL,随后即可以对该URL塞入HttpThread进行下载操作

//创建DownloadListener (webkit包)
class MyDownloadListenter implements DownloadListener{
  @Override
  public void onDownloadStart(String url, String userAgent,
    String contentDisposition, String mimetype, long contentLength) {
      System.out.println("url ==== >" + url);
      new HttpThread(url).start();
  }
    }
//给webview加入监听
webview.setDownloadListener(new MyDownloadListenter());

方法二:

直接发送一个action_view的intent即可

class MyDownloadListenter implements DownloadListener{
        @Override
        public void onDownloadStart(String url, String userAgent,
      String contentDisposition, String mimetype, long contentLength) {
  Uri uri = Uri.parse(url);
  Intent intent = new Intent(Intent.ACTION_VIEW, uri);
  startActivity(intent);
        }
    }


三:异常处理

当我们使用浏览器的时候,通常因为加载的页面的服务器的各种原因导致各种出错的情况,最平常的比如404错误,通常情况下浏览器会提示一个错误提示页面。事实上这个错误提示页面是浏览器在加载了本地的一个页面,用来提示用户目前已经出错了。

但是当我们的app里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面。

1. 首先我们需要些一个html文件,比如error_handle.html,这个文件里面就是当出错的时候需要展示给用户看的一个错误提示页面,尽量做的精美一些。然后将该文件放置到代码根目录的assets文件夹下。

2. 随后我们需要复写WebViewClient的onRecievedError方法,该方法传回了错误码,根据错误类型可以进行不同的错误分类处理

webview.setWebViewClient(new WebViewClient(){
        
      @Override
      public void onReceivedError(WebView view, int errorCode,
        String description, String failingUrl) {
    switch(errorCode)
    {
    case HttpStatus.SC_NOT_FOUND:
        view.loadUrl("file:///android_assets/error_handle.html");
        break;
    }
      }
  });
其实,当出错的时候,我们可以选择隐藏掉webview,而显示native的错误处理控件,这个时候只需要在onReceivedError里面显示出错误处理的native控件同时隐藏掉webview即可。


四:其它设置

按返回键时, 不退出程序而是返回上一浏览页面

public boolean onKeyDown(int keyCode, KeyEvent event) {       
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {       
        mWebView.goBack();       
        return true;       
        }       
    return super.onKeyDown(keyCode, event);       
    }
WebSettings 的常用方法介绍

setJavaScriptEnabled(true);  //支持js

setPluginsEnabled(true);  //支持插件 

setUseWideViewPort(false);  //将图片调整到适合webview的大小 

setSupportZoom(true);  //支持缩放 

setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局  

supportMultipleWindows();  //多窗口 

setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //关闭webview中缓存 

setAllowFileAccess(true);  //设置可以访问文件 

setNeedInitialFocus(true); //当webview调用requestFocus时为webview设置节点

webview webSettings.setBuiltInZoomControls(true); //设置支持缩放 

setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 

setLoadWithOverviewMode(true); // 缩放至屏幕的大小

setLoadsImagesAutomatically(true);  //支持自动加载图片
WebViewClient 的方法全解

doUpdateVisitedHistory(WebView view, String url, boolean isReload)  //(更新历史记录) 

onFormResubmission(WebView view, Message dontResend, Message resend) //(应用程序重新请求网页数据) 

onLoadResource(WebView view, String url) // 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。 

onPageStarted(WebView view, String url, Bitmap favicon) //这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。 

onPageFinished(WebView view, String url) //在页面加载结束时调用。同样道理,我们知道一个页面载入完成,于是我们可以关闭loading 条,切换程序动作。 

onReceivedError(WebView view, int errorCode, String description, String failingUrl)// (报告错误信息) 

onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)//(获取返回信息授权请求) 
 
onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) //重写此方法可以让webview处理https请求。
 
onScaleChanged(WebView view, float oldScale, float newScale) // (WebView发生改变时调用) 

onUnhandledKeyEvent(WebView view, KeyEvent event) //(Key事件未被加载时调用) 

shouldOverrideKeyEvent(WebView view, KeyEvent event)//重写此方法才能够处理在浏览器中的按键事件。 

shouldOverrideUrlLoading(WebView view, String url) 
//在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。

五: Android WebView缓存分析

WebView的缓存可以分为页面缓存和数据缓存。

页面缓存是指加载一个网页时的html、JS、CSS等页面或者资源数据。这些缓存资源是由于浏览器的行为而产生,开发者只能通过配置HTTP响应头影响浏览器的行为才能间接地影响到这些缓存数据。

他们的索引存放在/data/data/package_name/databases下。他们的文件存放在/data/data/package_name/cache/xxxwebviewcachexxx下。文件夹的名字在2.x和4.x上有所不同,但都文件夹名字中都包含webviewcache。


数据缓存分为两种:AppCache和DOM Storage(Web Storage)。他们是因为页面开发者的直接行为而产生。所有的缓存数据都由开发者直接完全地掌控。
AppCache使我们能够有选择的缓冲web浏览器中所有的东西,从页面、图片到脚本、css等等。尤其在涉及到应用于网站的多个页面上的CSS和JavaScript文件的时候非常有用。其大小目前通常是5M。
在Android上需要手动开启(setAppCacheEnabled),并设置路径(setAppCachePath)和容量(setAppCacheMaxSize)
Android中Webkit使用一个db文件来保存AppCache数据(my_path/ApplicationCache.db)
更详细的资料可以参考这里:http://www.itboat.net/thread-23674-1-1.html

如果需要存储一些简单的用key/value对即可解决的数据,DOM Storage是非常完美的方案。根据作用范围的不同,有Session Storage和Local Storage两种,分别用于会话级别的存储(页面关闭即消失)和本地化存储(除非主动删除,否则数据永远不会过期)。
在Android中可以手动开启DOM Storage(setDomStorageEnabled),设置存储路径(setDatabasePath)
Android中Webkit会为DOM Storage产生两个文件(my_path/localstorage/http_h5.m.taobao.com_0.localstorage和my_path/localstorage/Databases.db)。

另外,在Android中清除缓存时,如果需要清除Local Storage的话,仅仅删除Local Storage的本地存储文件是不够的,内存里面有缓存数据。如果再次进入页面,Local Storage中的缓存数据同样存在。需要杀死程序运行的当前进程再重新启动才可以。


一边学习一边通过博客记录,很多是摘录其他人的。

本期节目就到这里,感谢您的收看,下期再见~











你可能感兴趣的:(android,html5,移动,webView)