android系统浏览器下载流程

本文详细分析了Android系统浏览器的下载流程,从Tab.setWebView开始,经过WebViewController和DownloadHandler的处理,通过DownloadManager.enqueue插入数据库,由DownloadProvider启动DownloadService进行下载。在DownloadService中,通过DownloadThread执行实际的文件下载,并实时更新数据库以显示下载进度。
摘要由CSDN通过智能技术生成

android系统浏览器下载流程

标签: android browser download

简介

当我们用浏览器点开一个下载链接,然后去下载,从宏观上认识,有下载进度的实时更新和界面的跳转。整个过程中,主要涉及到以下过程。浏览器点击下载按钮,浏览器分发下去一个下载请求,跳转界面的同时在DownloadProvider进程中去真正的下载数据以及更新数据库,在界面上监听数据库的变化,去实时更新相关进度。全过程中,Browser进程负责分发下载请求,DownloadProvider进程负责真正的下载操作。

目前而言,主要有两种结构,C-S和B-S结构。对于Browser来说,主要在于对Webview这个控件的认识,底层的内核实现也是非常复杂,这里我们不做讨论。对于一个浏览器链接,webkit底层会去解析,同时也会判断这个链接属于什么类型。比如我们今天的这个下载链接,Browser就有专门的下载监听器去回调执行这个action,下面我们会详细分析。

WebView控件简单介绍

WebView控件提供了一个内嵌的浏览器试图,用于显示本地的html或网路上的网页。
并且比较强大的是,还可以直接跟js相互调用。
WebView有两个方法:setWebChromeClient和setWebClient
WebChromeClient:主要处理解析,渲染网页等浏览器做的事情,也是辅助WebView处理Javascript 的对话框,网站图标,网站title,加载进度等
WebViewClient :就是帮助WebView处理各种通知、请求事件的。

Browser下载的时序图。

这里写图片描述


下面来详细分析具体的代码实现细节,时序图是更加细节的步骤,这里我们着重分析下面的流程。


Step 1:Tab.setWebView
      void setWebView(WebView w, boolean restore) {
        ....
        mMainView = w;
        // attach the WebViewClient, WebChromeClient and DownloadListener
        if (mMainView != null) {
            mMainView.setWebViewClient(mWebViewClient);
            mMainView.setWebChromeClient(mWebChromeClient);
            mMainView.setDownloadListener(mDownloadListener);
            ....
        }
    }

这个方法定义在packages/apps/Browser/src/com/android/browser/Tab.java
浏览器是用过Webview来显示UI。这里设置了一个WebView对象,然后setWebViewClient和setWebChromeClient主要设置了对页面加载以及js的处理。这里我们只分析setDownloadListener这个监听,首先要理解一点,对于WebView上的一个下载按钮,它的事件是怎么处理的,浏览器如何判断这个是下载?以上其实浏览器内核已经处理,浏览器内核是根据指定的url判断该链接是否是一个下载链接,如果点击的是一个下载链接,那么最终会回调到该监听器中去处理,具体底层实现比较复杂,暂不作讨论。

 Tab(WebViewController wvcontroller, WebView w, Bundle state) {
        /// M: add for save page
        ....
        mDownloadListener = new BrowserDownloadListener() {
            public void onDownloadStart(String url, String userAgent,
                    String contentDisposition, String mimetype, String referer,
                    long contentLength) {
                /// M: add for fix download page url
                mCurrentState.mIsDownload = true;
                mWebViewController.onDownloadStart(Tab.this, url, userAgent, contentDisposition,
                        mimetype, referer, contentLength);
            }
        };
        ....
        setWebView(w);
        ....
    }

这个方法定义在packages/apps/Browser/src/com/android/browser/Tab.java
分析Tab的构造方法,这里主要看BrowserDownloadListener这个对象。当点击了下载按钮,则会去回调BrowserDownloadListener的onDownloadStart方法,这个最终是委托给了mWebViewController去处理。

Step 2:WebViewController.onDownloadStart
    @Override
    public void onDownloadStart(Tab tab, String url, String userAgent,
            String contentDisposition, String mimetype, String referer,
            long contentLength) {
        ....
        DownloadHandler.onDownloadStart(mActivity, url, userAgent,
                contentDisposition, mimetype, referer, false, contentLength);
        ...
    }

这个方法定义在packages/apps/Browser/src/com/android/browser/Controller.java
WebViewController是一个接口,Controller是它的具体实现,在onDownloadStart方法中,实现比较简单,直接是将参数委托给DownloadHandler的静态方法onDownloadStart去进一步处理。
在这里,参数:
url下载的网址链接
userAgent浏览器userAgent信息
mimetype下载内容的type类型
contentLength下载内容大小

Step 3:DownloadHandler.onDownloadStart

这个方法定义在packages/apps/Browser/src/com/android/browser/DownloadHandler.java
实现很简单,直接将参数继续传递到onDownloadStartNoStream方法。

Step 4:DownloadHandler.onDownloadStartNoStream
    /*package */
    public static void onDownloadStartNoStream(Activity activity,
            String url, String userAgent, String contentDisposition,
            String mimetype, String referer, boolean privateBrowsing, long contentLength) {
        ....
        // java.net.URI is a lot stricter than KURL so we have to encode some
        // extra characters. Fix for b 2538060 and b 1634719
        WebAddress webAddress;
        try {
            webAddress = new WebAddress(url);
            webAddress.setPath(encodePath(webAddress.getPath()));
        } catch (Exception e) {
            // This only happens for very bad urls, we want to chatch the
            // exception here
            Log.e(LOGTAG, "Exception trying to parse url:" + url);
            return;
        }

        String addressString = webAddress.toString();
        Uri uri = Uri.parse(addressString);
        final DownloadManager.Request request = new DownloadManager.Request(uri);
        request.setMimeType(mimetype);

        // let this downloaded file be scanned by MediaScanner - so that it can
        // show up in Gallery app, for example.
        request.allowScanningByMediaScanner();
        request.setDescription(webAddress.getHost());
        // XXX: Have to use the old url since the cookies were stored using the
        // old percent-encoded url.
        String cookies = CookieManager.getInstance().getCookie(url, privateBrowsing);
        request.addRequestHeader("cookie", cookies);
        request.addRequestHeader("User-Agent", userAgent);
        request.addRequestHeader("Referer", referer);
        request.setNotificationVisibility(
                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setUserAgent(userAgent);

        final DownloadManager manager = (DownloadManager)   
                        activity.getSystemService(Context.DOWNLOAD_SERVICE);
        new Thread("Browser download") {
                public void run() {
                    manager.enqueue(request);
                }
        }.start();
        /// M: Add to start Download activity. @{
   
        Intent pageView = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
        pageView.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(pageView);
        /// @}
    }

这个方法定义在packages/apps/Browser/src/com/android/browser/DownloadHandler.java
在该方法中,主要做了三件事
1.将下载信息url,minetype等封装成一个Request对象,供后续使用。
2.获取一个DownloadManager

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值