浏览器探究——下载

浏览器探究——下载

当前我的机器还是无网络状态,以下讨论可能有错误

长按一个链接,会调用到BrowserActivity.onContextItemSelected,进而调用Controller. onContextItemSelected。在处理该菜单项时,会调用当前WebView的requestFocusNodeHref。

/**

     * Request the anchor orimage element URL at the last tapped point.

     * If hrefMsg is null,this method returns immediately and does not

     * dispatch hrefMsg to itstarget. If the tapped point hits an image,

     * an anchor, or an imagein an anchor, the message associates

     * strings in named keysin its data. The value paired with the key

     * may be an empty string.

     *

     * @param hrefMsg Thismessage will be dispatched with the result of the

     *                request. The message datacontains three keys:

     *                - "url" returns theanchor's href attribute.

     *                - "title" returns theanchor's text.

     *                - "src" returns theimage's src attribute.

     */

这里有个要注意的,Controller运行在主线程中,并且Controller有个Handler。现在Controller想去WebViewCoreThread线程中获取一些数据,它是怎么做的呢?首先在Controller处利用Controller的Handler创建一个Message,然后把这个Message(假定为Message1)作为一个数据参数,向WebViewCore发送Message(假定为Message2),即Message1是Message2的一个数据参数。WebViewCore自然可以接收到Message2并处理他,把处理后的数据放入到Message1中,然后发送出去,由于Message1是利用Controller的Handler创建的,自然Controller的Handler会在主线程中接收到这个Message1,然后就可以从Message1中获取到他最初所期望获取的数据了。

看下实际的情况,Controller在调用WebView.requestFocusNodeHref之前就利用自己的Handler创建了一个Message(Message1),该参数的what值为FOCUS_NODE_HREF并设置了一些参数信息,这个Message作为WebView.requestFocusNodeHref的参数。

WebView.requestFocusNodeHref会计算当前按下的坐标位置,然后将这些信息作为参数发送REQUEST_CURSOR_HREF消息给WebViewCoreThread线程,当然刚刚创建的Message(Message1)也作为一个参数。WebViewCoreThread线程通过三个JNI函数nativeRetrieveHref,nativeRetrieveAnchorText,nativeRetrieveImageSource获取到坐标所指向的链接的url,title,src,这个所谓的src应该是个图标吧。然后把这些信息存入Message1中再返还给主线程。

此时主线程接收到回传的Message1,Controller的Handler被调用并处理FOCUS_NODE_HREF消息。这个流程很有用,不仅仅保存链接使用了这个流程,还有些其他的涉及到获取链接的功能也走这个流程,比如拷贝链接。

在接收到消息和解出数据后,调用DownloadHandler.onDownloadStartNoStream这个静态函数。

/**

    * Notify the host application a download should be done, even if there

    * is a streaming viewer available for thise type.

    * @param activity Activity requesting the download.

    * @param url The full url to the content that should be downloaded

    * @param userAgent User agent of the downloading application.

    * @param contentDisposition Content-disposition http header, if present.

    * @param mimetype The mimetype of the content reported by the server

    * @param privateBrowsing If the request is coming from a privatebrowsing tab.

    */

这个函数是个重要的函数,负责下载资源的处理。

该函数主要做以下处理:

1.        通过url等信息获取文件名。

2.        判断SD卡是否存在。

3.        如果当前不知道mimeType则进行获取。

4.        利用DownloadManager.Request和DownloadManager进行资源的下载。

5.        显示通知信息。

这里主要看下1和3项。

其中2项采用标准判断SD卡方式,如果不存在SD卡则提示用户,并直接返回不进行下载。

4项采用DownloadManager标准的设置参数和开始下载的方式。此处需要注意的是这里会开启一个新线程来执行DownloadManager.enqueue操作。

5项目只是简单的使用Toast显示了下载通知。

1项通过静态函数URLUtil.guessFileName获取文件名

/**

    * Guesses canonical filename that a download would have, using

    * the URL and contentDisposition. File extension, if not defined,

    * is added based on the mimetype

    * @param url Url to the content

    * @param contentDisposition Content-Disposition HTTP header or null

    * @param mimeType Mime-type of the content or null

    *

    * @return suggested filename

    */

该函数通过一些分析规则和匹配规则来从url,contentDisposition,mimeType中获取到一个文件名。

3项当当前的mimeType为null是会通过FetchUrlMimeType类来获取资源实际的mimeType。

FetchUrlMimeType

/**

 *This class is used to pull down the http headers of a given URL so that

 * wecan analyse the mimetype and make any correction needed before we give

 *the URL to the download manager.

 *This operation is needed when the user long-clicks on a link or image and

 * wedon't know the mimetype. If the user just clicks on the link, we will

 * dothe same steps of correcting the mimetype down in

 *android.os.webkit.LoadListener rather than handling it here.

 *

 */

class FetchUrlMimeType extends Thread

可见FetchUrlMimeType是一个线程类,会在一个单独的线程中执行他的处理操作。这个类的处理其实就是发送一个http请求给这个资源,通过http response的头信息来获取资源实际的mimeType。http请求的处理是通过AndroidHttpClient类,HttpHost类,HttpHead类,ConnRouteParams类,HttpResponse类,Header类,这些类完成的,以上都是net或apache-http模块提供的。

如果成功的获取到实际的mimeType,会再次调用URLUtil.guessFileName获取一个文件名。

以上内容做完后,再使用DownloadManager进行下载的操作,注意这里不需要再创建一个新线程执行DownloadManager.enqueue了,因为FetchUrlMimeType本身就是个线程类,现在已经是在一个单独的线程中了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值