Android开发之WebView的使用(2)

在上一篇中我们说了WebView的基本使用安卓开发之WebView的使用(1),里面提到了WebViewClient和WebChromeClient。
下面我们来探究一番WebViewClient和WebChromeClient

Let's Go

先了解一下概念

Android WebView做为承载网页的载体控件,他在网页显示的过程中会产生一些事件,并回调给我们的应用程序,以便我们在网页加载过程中做应用程序想处理的事情。比如说客户端需要显示网页加载的进度、网页加载发生错误等等事件。

WebView提供两个事件回调类给应用层,分别为WebViewClient和WebChromeClient。我们可以继承这两个类,接受相应事件处理。

WebViewClient: 主要提供网页加载各个阶段的通知,比如网页开始加载onPageStarted,网页结束加载onPageFinished等。

WebChromeClient: 主要提供网页加载过程中提供的数据内容,比如返回网页的title,favicon等。

下面先从WebViewClient开始说起

WebViewClient的基本使用

WebViewClient的基本使用

创建WebViewClient实例并设置到WebView对象中,具体代码参考如下:

class MyAndroidWebViewClient extends WebViewClient {  
    @Override  
    public void onPageStarted(WebView view, String url, Bitmap favicon) {  
       // TODO  
    }  
      
    @Override  
    public void onPageFinished(WebView view, String url) {  

    }  
}  
webview.setWebViewClient(new MyAndroidWebViewClient ());  

来看看API

  • public boolean shouldOverrideUrlLoading(WebView view, String url)
    当加载的网页需要重定向的时候就会回调这个函数告知我们应用程序是否需要接管控制网页加载,如果应用程序接管,并且return true意味着主程序接管网页加载,如果返回false让webview自己处理。
    参数说明:
    @param view 接收WebViewClient的那个实例
    @param url 即将要被加载的url
    @return true 当前应用程序要自己处理这个url, 返回false则不处理。
    Tips:
    (1) 当请求的方式是"POST"方式时这个回调是不会通知的。
    (2) 当我们访问的地址需要我们应用程序自己处理的时候,可以在这里截获,比如我们发现跳转到的是一个market的链接,那么我们可以直接跳转到应用市场,或者其他app。

  • public void onPageStarted(WebView view, String url, Bitmap favicon)
    当内核开始加载访问的url时,会通知应用程序,对每个main frame这个函数只会被调用一次,页面包含iframe 或者framesets 不会另外调用一次onPageStarted,当网页内内嵌的frame 发生改变时也不会调用onPageStarted。
    参数说明:
    @param view 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param url 即将要被加载的url
    @param favicon 如果这个favicon已经存储在本地数据库中,则会返回这个网页的favicon,否则返回为null。
    Tips:
    (1) iframe 可能不少人不知道什么含义,这里我解释下,iframe我们加载的一张,下面有很多链接,我们随便点击一个链接是即当前host的一个iframe.
    (2) 有个问题可能是开发者困惑的,onPageStarted和shouldOverrideUrlLoading 在网页加载过程中这两个函数到底哪个先被调用。当我们通过loadUrl的方式重新加载一个网址时候,这时候会先调用onPageStarted再调用shouldOverrideUrlLoading,当我们在打开的这个网址点击一个link,这时候会先调用shouldOverrideUrlLoading再调用onPageStarted。
    不过shouldOverrideUrlLoading不一定每次都被调用,只有需要的时候才会被调用。

  • public void onPageFinished(WebView view, String url)
    当内核加载完当前页面时会通知我们的应用程序,这个函数只有在main frame情况下才会被调用,当调用这个函数之后,渲染的图片不会被更新,如果需要获得新图片的通知可以使用@link WebView.PictureListener#onNewPicture。
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param url 即将要被加载的url

  • public void onLoadResource(WebView view, String url)
    通知应用程序WebView即将加载url 制定的资源
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param url 即将加载的url 资源

  • public WebResourceResponse shouldInterceptRequest(WebView view, String url)
    通知应用程序内核即将加载url制定的资源,应用程序可以返回本地的资源提供给内核,若本地处理返回数据,内核不从网络上获取数据。
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param url raw url 制定的资源
    @return 返回WebResourceResponse包含数据对象,或者返回null
    Tips
    这个回调并不一定在UI线程执行,所以我们需要注意在这里操作View或者私有数据相关的动作。
    如果我们需要改变网页的背景,或者需要实现网页页面颜色定制化的需求,可以在这个回调时机处理。

  • public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    当浏览器访问制定的网址发生错误时会通知我们应用程序,比如网络错误。
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param errorCode 错误号可以在WebViewClient.ERROR 里面找到对应的错误名称。
    @param description 描述错误的信息
    @param failingUrl 当前访问失败的url,注意并不一定是我们主url
    Tips
    在onReceiveError我们可以自定义网页的错误页面。

  • public void onFormResubmission(WebView view, Message dontResend, Message resend)
    如果浏览器需要重新发送POST请求,可以通过这个时机来处理。默认是不重新发送数据。
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param dontResent 当浏览器不需要重新发送数据时,可以使用这个参数。
    @param resent 当浏览器需要重新发送数据时, 可以使用这个参数。

  • public void doUpdateVisitedHistory(WebView view, String url, boolean isReload)
    通知应用程序可以将当前的url存储在数据库中,意味着当前的访问url已经生效并被记录在内核当中。
    这个函数在网页加载过程中只会被调用一次。注意网页前进后退并不会回调这个函数。
    参数说明:
    @param view 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param url 当前正在访问的url
    @ param isReload 如果是true 这个是正在被reload的url

  • public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
    当网页加载资源过程中发现SSL错误会调用此方法。我们应用程序必须做出响应,是取消请求handler.cancel(),还是继续请求handler.proceed();内核的默认行为是handler.cancel();
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param handler 处理用户请求的对象。
    @param error SSL错误对象
    Tips
    内核会记住本次选择,如果下次还有相同的错误,内核会直接执行之前选择的结果。

  • public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
    通知应用程序WebView接收到了一个Http auth的请求,应用程序可以使用supplied 设置webview的响应请求。默认行为是cancel 本次请求。
    参数说明:
    @param view 接收WebViewClient的那个实例,
    前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param handler 用来响应WebView请求的对象
    @param host 请求认证的host
    @param realm 认真请求所在的域

  • public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
    提供应用程序同步一个处理按键事件的机会,菜单快捷键需要被过滤掉。如果返回true,webview不处理该事件,如果返回false, webview会一直处理这个事件,因此在view 链上没有一个父类可以响应到这个事件。默认行为是return false;
    参数说明:
    @param view 接收WebViewClient的那个实例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是这个webview。
    @param event 键盘事件名
    @return 如果返回true,应用程序处理该时间,返回false 交有webview处理。

  • public void onScaleChanged(WebView view, float oldScale, float newScale)
    通知应用程序webview 要被scale。应用程序可以处理改事件,比如调整适配屏幕。

  • public void onReceivedLoginRequest(WebView view, String realm, String account, String args)
    通知应用程序有个自动登录的帐号过程
    参数说明:
    @param view 请求登陆的webview
    @param realm 账户的域名,用来查找账户。
    @param account 一个可选的账户,如果是null 需要和本地的账户进行check, 如果是一个可用的账户,则提供登录。
    @param args 验证制定参数的登录用户

WebChromeClient基本使用

API

  • public void onProgressChanged(WebView view, int newProgress)
    通知应用程序当前网页加载的进度。
    参数说明:
    @param view WebView
    @newProgress 进度

  • public void onReceivedTitle(WebView view, String title)
    当document 的title变化时,会通知应用程序
    参数说明:
    @param view WebView
    @param title document的title
    Tips
    这个函数调用时机不确定,有可能很早,有可能很晚,取决于网页把title设置在什么位置,
    大多数网页一般把title设置到页面的前面,因此很多情况会比较早回调到这个函数。

  • public void onReceivedIcon(WebView view, Bitmap icon)
    当前页面有个新的favicon时候,会回调这个函数。
    参数说明:
    @param view WebView
    @param icon 当前页面的favicon

  • public void onReceivedTouchIconUrl(WebView view, String url, boolean precomposed)
    通知应用程序 apple-touch-icon的 url
    参数说明:
    @param view WebView
    @param url apple-touch-icon 的服务端地址
    @param precomposed 如果precomposed 是true 则touch-icon是预先创建的
    Tips
    如果应用程序需要这个icon的话, 可以通过这个url获取得到 icon。

  • public void onShowCustomView(View view, CustomViewCallback callback)
    view,主要是用在视频全屏HTML5 Video support。
    参数说明:
    @param view 即将要显示的view
    @param callback 当view 需要dismiss 则使用这个对象进行回调通知。

  • public void onHideCustomView()
    隐藏view,如退出视频通知

  • public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
    请求创建一个新的窗口,如果我们应用程序接管这个请求,必须返回true,并且创建一个新的webview来承载主窗口。如果应用程序不处理,则需要返回false,默认行为和返回false表现一样。
    参数说明:
    @param view 请求创建新窗口的webview
    @param isUserGesture 如果是true,则说明是来自用户收拾操作行为,比如用户点击链接
    @param isDialog true 请求创建的新窗口必须是个dialog,而不是全屏的窗口。
    @param resultMsg 当webview创建时需要发送一个消息。WebView.WebViewTransport.setWebView(WebView)
    Tips 具体例子如下:

private void createWindow(final Message msg){  
    WebView.WebViewTransport transport = (WebView.WebViewTransport) msg.obj;  
    final Tab newTab = mWebViewController.openTab(null, Tab.this, true,  true);  
    transport.setWebView(newTab.getWebView());  
    msg.sendToTarget();  
}  
  • public void onRequestFocus(WebView view)
    webview请求得到focus,发生这个主要是当前webview不是前台状态,是后台webview。

  • public void onCloseWindow(WebView window)
    通知应用程序从关闭传递过来的webview并从view tree中remove。

  • public boolean onJsAlert(WebView view, String url, String message, JsResult result)
    通知应用程序显示javascript alert对话框,如果应用程序返回true内核认为应用程序处理这个消息,返回false,内核自己处理。
    参数说明:
    @param view webview。
    @param url 当前请求弹出javascript 对话框webview 加载的url地址。
    @param message 弹出的内容信息
    @result 用来响应用户的处理。
    Tips
    如果我们应用接管处理, 则必须给出result的结果,result.cancel,result.comfirm必须调用其中之后,否则内核会hang住。

  • public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
    通知应用程序提供confirm 对话框。 参数说明同上onJsAlert

  • public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
    通知应用程序显示一个prompt对话框。
    Tips
    必须调用result.confirm 方法如果应用程序接管这个方法。

  • public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result)
    通知应用程序显示一个对话框,让用户选择是否离开当前页面,这个回调是javascript中的onbeforeunload事件,如果客户端返回true,内核会认为客户端提供对话框。默认行为是return false。
    参数说明和之前介绍的onJsAlert()相同。

  • public void onExceededDatabaseQuota(String url, String databaseIdentifier, long quota, long estimatedDatabaseSize, long totalQuota, WebStorage.QuotaUpdater quotaUpdater)
    通知应用程序webview内核web sql 数据库超出配额,请求是否扩大数据库磁盘配额。默认行为是不会增加数据库配额。
    参数说明:
    @param url 触发这个数据库配额的url地址
    @param databaseIdentifier 指示出现数据库超过配额的标识。
    @param quota 原始数据库配额的大小,是字节单位bytes
    @param estimatedDatabaseSize 到达底线的数据大小 bytes
    @param totalQuota 总的数据库配额大小 bytes
    @param quotaUpdater 更新数据库配额的对象,可以使用 quotaUpdater.updateQuota(newQuota);配置新的数据库配额大小。

  • public void onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)
    通知应用程序内核已经到达最大的appcache。appcache是HTML5针对offline的一个数据处理标准。

  • public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback)
    当前页面请求是否允许进行定位。
    GeolocationPermissions.Callback的方法:
    1.public void invoke(String origin, boolean allow, boolean retain);
    参数说明:
    @param origin 权限设置的源地址
    @param allow 是否允许定位
    @retain 当前的选择是否让内核记住。
    2.public void onGeolocationPermissionsHidePrompt()

  • public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture)
    这个回调是私有回调, 当页面需要请求打开系统的文件选择器,则会回调这个方法,比如我们需要上传图片,请求拍照,邮件的附件上传等等操作。如果不实现这个私有API,则上面的请求都将不会执行。

千言万语,不如来个Demo
GitHub: https://github.com/Rairmmd/RairDemo/tree/master/WebViewDemo
Coding:https://git.coding.net/Rair/RairDemo.git

推荐阅读更多精彩内容