`

android下载封装类Download,支持断点下载

阅读更多
各种回调, 支持断点下载

public class Download implements Serializable {
    private static final int START = 1;                 // 开始下载
    private static final int PUBLISH = 2;               // 更新进度
    private static final int PAUSE = 3;                 // 暂停下载
    private static final int CANCEL = 4;                // 取消下载
    private static final int ERROR = 5;                 // 下载错误
    private static final int SUCCESS = 6;               // 下载成功
    private static final int GOON = 7;                  // 继续下载
      
    private static ExecutorService mThreadPool;         // 线程池
      
    static {
        mThreadPool = Executors.newFixedThreadPool(5);  // 默认5个 
    }
          
    private int mDownloadId;                            // 下载id
    private String mFileName;                           // 本地保存文件名
    private String mUrl;                                // 下载地址
    private String mLocalPath;                          // 本地存放目录
  
    private boolean isPause = false;                    // 是否暂停
    private boolean isCanceled = false;                 // 是否手动停止下载
      
    private OnDownloadListener mListener;               // 监听器
      
    /**
     * 配置下载线程池的大小
     * @param maxSize 同时下载的最大线程数
     */
    public static void configDownloadTheadPool(int maxSize) {
        mThreadPool = Executors.newFixedThreadPool(maxSize);
    }
      
    /**
     * 添加下载任务
     * @param downloadId 下载任务的id
     * @param url        下载地址
     * @param localPath   本地存放地址
     */
    public Download(int downloadId, String url, String localPath) {
        if (!new File(localPath).exists()) {
            new File(localPath).mkdirs();
        }
          
        Log.log("下载地址;" + url);
          
        mDownloadId = downloadId;
        mUrl = url;
        String[] tempArray = url.split("/");
        mFileName = tempArray[tempArray.length-1];
        mLocalPath = localPath;
    }
      
    /**
     * 设置监听器
     * @param listener 设置下载监听器
     * @return this
     */
    public Download setOnDownloadListener(OnDownloadListener listener) {
        mListener = listener;
        return this;
    }
      
    /**
     * 获取文件名
     * @return 文件名
     */
    public String getFileName() {
        return mFileName;
    }
  
    /**
     * 开始下载
     * params isGoon是否为继续下载
     */
    public void start(final boolean isGoon) {
        // 处理消息
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case ERROR:
                    mListener.onError(mDownloadId);
                    break;
                case CANCEL:
                    mListener.onCancel(mDownloadId);
                    break;
                case PAUSE:
                    mListener.onPause(mDownloadId);
                    break;
                case PUBLISH:
                    mListener.onPublish(mDownloadId, Long.parseLong(msg.obj.toString()));
                    break;
                case SUCCESS:
                    mListener.onSuccess(mDownloadId);
                    break;
                case START:
                    mListener.onStart(mDownloadId, Long.parseLong(msg.obj.toString()));
                    break;
                case GOON:
                    mListener.onGoon(mDownloadId, Long.parseLong(msg.obj.toString()));
                    break;
                }
            }
        };
          
        // 真正开始下载
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                download(isGoon,handler);
            }
        });
    }
      
    /**
     * 下载方法
     * @param handler 消息处理器
     */
    private void download(boolean isGoon, Handler handler) {
        Message msg = null;
        Log.log("开始下载。。。");
        try {
            RandomAccessFile localFile = new RandomAccessFile(new File(
                    mLocalPath + File.separator + mFileName), "rwd");
  
            DefaultHttpClient client = new DefaultHttpClient();
            client.setParams(getHttpParams());
            HttpGet get = new HttpGet(mUrl);
  
            long localFileLength = getLocalFileLength();
            final long remoteFileLength = getRemoteFileLength();
            long downloadedLength = localFileLength;
              
            // 远程文件不存在
            if (remoteFileLength == -1l) {
                Log.log("下载文件不存在...");
                localFile.close();
                handler.sendEmptyMessage(ERROR);
                return;
            }
  
            // 本地文件存在
            if (localFileLength > -1l && localFileLength < remoteFileLength) {
                Log.log("本地文件存在...");
                localFile.seek(localFileLength);
                get.addHeader("Range", "bytes=" + localFileLength + "-"
                        + remoteFileLength);
            }
              
            msg = Message.obtain();
              
            // 如果不是继续下载
            if(!isGoon) {
                // 发送开始下载的消息并获取文件大小的消息
                msg.what = START;
                msg.obj = remoteFileLength;
            }else {
                msg.what = GOON;
                msg.obj = localFileLength;
            }
              
            handler.sendMessage(msg);
              
            HttpResponse response = client.execute(get);
            int httpCode = response.getStatusLine().getStatusCode();
            if (httpCode >= 200 && httpCode <= 300) {
                InputStream in = response.getEntity().getContent();
                byte[] bytes = new byte[1024];
                int len = -1;
                while (-1 != (len = in.read(bytes))) {
                    localFile.write(bytes, 0, len);
                    downloadedLength += len;
//                  Log.log((int)(downloadedLength/(float)remoteFileLength * 100));
                    if ((int)(downloadedLength/(float)remoteFileLength * 100) % 10 == 0) {
                        // 发送更新进度的消息
                        msg = Message.obtain();
                        msg.what = PUBLISH;
                        msg.obj = downloadedLength;
                        handler.sendMessage(msg);
//                      Log.log(mDownloadId + "已下载" + downloadedLength);
                    }
                      
                    // 暂停下载, 退出方法
                    if (isPause) {
                        // 发送暂停的消息
                        handler.sendEmptyMessage(PAUSE);
                        Log.log("下载暂停...");
                        break;
                    }
                      
                    // 取消下载, 删除文件并退出方法
                    if (isCanceled) {
                        Log.log("手动关闭下载。。");
                        localFile.close();
                        client.getConnectionManager().shutdown();
                        new File(mLocalPath + File.separator + mFileName)
                                .delete();
                        // 发送取消下载的消息
                        handler.sendEmptyMessage(CANCEL);
                        return;
                    }
                }
  
                localFile.close();
                client.getConnectionManager().shutdown();
                // 发送下载完毕的消息
                if(!isPause) handler.sendEmptyMessage(SUCCESS);
            }
  
        } catch (Exception e) {
            // 发送下载错误的消息
            handler.sendEmptyMessage(ERROR);
        }
    }
  
    /**
     * 暂停/继续下载
     * param pause 是否暂停下载
     * 暂停 return true
     * 继续 return false
     */
    public synchronized boolean pause(boolean pause) {
        if(!pause) {
            Log.log("继续下载");
            isPause = false;
            start(true); // 开始下载
        }else {
            Log.log("暂停下载");
            isPause = true;
        }
        return isPause;
    }
  
    /**
     * 关闭下载, 会删除文件
     */
    public synchronized void cancel() {
        isCanceled = true;
        if(isPause) {
            new File(mLocalPath + File.separator + mFileName)
            .delete();
        }
    }
  
    /**
     * 获取本地文件大小
     * @return 本地文件的大小 or 不存在返回-1
     */
    public synchronized long getLocalFileLength() {
        long size = -1l;
        File localFile = new File(mLocalPath + File.separator + mFileName);
        if (localFile.exists()) {
            size = localFile.length();
        }
        Log.log("本地文件大小" + size);
        return size <= 0 ? -1l : size;
    }
  
    /**
     * 获取远程文件打下 or 不存在返回-1
     * @return
     */
    public synchronized long getRemoteFileLength() {
        long size = -1l;
        try {
            DefaultHttpClient client = new DefaultHttpClient();
            client.setParams(getHttpParams());
            HttpGet get = new HttpGet(mUrl);
  
            HttpResponse response = client.execute(get);
            int httpCode = response.getStatusLine().getStatusCode();
            if (httpCode >= 200 && httpCode <= 300) {
                size = response.getEntity().getContentLength();
            }
  
            client.getConnectionManager().shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
  
        Log.log("远程文件大小" + size);
        return size;
    }
  
    /**
     * 设置http参数 不能设置soTimeout
     * @return HttpParams http参数
     */
    private static HttpParams getHttpParams() {
        HttpParams params = new BasicHttpParams();
  
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
        HttpProtocolParams.setUseExpectContinue(params, true);
        HttpProtocolParams
                .setUserAgent(
                        params,
                        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2041.4 Safari/537.36");
        ConnManagerParams.setTimeout(params, 4000);
        HttpConnectionParams.setConnectionTimeout(params, 4000);
          
        return params;
    }
      
    /**
     * 关闭下载线程池
     */
    public static void closeDownloadThread() {
        if(null != mThreadPool) {
            mThreadPool.shutdownNow();
        }
    }
  
    public interface OnDownloadListener {
        public void onStart(int downloadId, long fileSize);  // 回调开始下载
        public void onPublish(int downloadId, long size);    // 回调更新进度
        public void onSuccess(int downloadId);               // 回调下载成功
        public void onPause(int downloadId);                 // 回调暂停
        public void onError(int downloadId);                 // 回调下载出错
        public void onCancel(int downloadId);                // 回调取消下载
        public void onGoon(int downloadId, long localSize);  // 回调继续下载
    }
}


调用,如下:
Download d = new Download(1, "http://baidu.com/test.zip","/sdcard/download/");
            d.setOnDownloadListener(new Download.OnDownloadListener() {
                @Override
                public void onSuccess(int downloadId) {
                    System.out.println(downloadId + "下载成功");
                }
      
                @Override
                public void onStart(int downloadId, long fileSize) {
                    System.out.println(downloadId + "开始下载,文件大小:" + fileSize);
                }
      
                @Override
                public void onPublish(int downloadId, long size) {
                    System.out.println("更新文件" + downloadId + "大小:" + size);
                }
      
                @Override
                public void onPause(int downloadId) {
                    System.out.println("暂停下载" + downloadId);
                }
      
                @Override
                public void onGoon(int downloadId, long localSize) {
                    System.out.println("继续下载" + downloadId);
                }
      
                @Override
                public void onError(int downloadId) {
                    System.out.println("下载出错" + downloadId);
                }
      
                @Override
                public void onCancel(int downloadId) {
                    System.out.println("取消下载" + downloadId);
                }
            });
      
            d.start(false);


原址
http://www.oschina.net/code/snippet_1021353_38517#57000
分享到:
评论

相关推荐

    android多线程断点下载

    本文将详细介绍如何在Android中实现多线程断点下载,以及如何封装一个易于使用的接口,使得即使是对Android不太熟悉的开发者也能快速上手。 首先,我们要理解什么是多线程下载。传统的单线程下载方式只有一个线程...

    Android多线程断点文件下载和暂停源码

    它可能包含了`DownloadTask`类来封装每个线程的下载任务,`DownloadManager`类用于管理线程池和下载状态,以及一些辅助类如`DownloadService`用于后台运行下载任务。通过阅读源码,我们可以学习到如何在Android中...

    Android-使用AsyncTask实现的多任务多线程下载的Demo支持断点续传。

    这个Demo,"Android-使用AsyncTask实现的多任务多线程下载的Demo支持断点续传",展示了如何高效且智能地管理下载过程。我们将深入探讨AsyncTask、多线程以及断点续传的概念。 首先,`AsyncTask`是Android提供的一种...

    android断点续传demo

    Android提供了DownloadManager类,它是系统级的服务,支持断点续传。通过它,开发者可以方便地创建、查询和管理下载任务,系统会自动处理网络变化和错误重试。然而,使用DownloadManager需要处理更多的细节,比如...

    Android 常用封装库

    10. **下载管理**:对于大文件下载,通常需要后台管理,如`DownloadManager`系统服务,它可以实现断点续传和后台下载。另外,第三方库如`AQuery`、`Loopj Android Async HTTP`也提供了下载功能。 11. **数据库管理*...

    多线程断点下载

    实现多线程断点下载,首先需要创建一个封装类,用于处理线程管理和进度记录。这个封装类可能包含以下功能: 1. **初始化线程池**:根据文件大小和网络条件设定合理的线程数量,通常3-5个线程比较合适。 2. **分配...

    Android 下载文件Demo

    - 使用DownloadManager API:Android系统提供了DownloadManager服务,可以方便地实现后台下载,并提供通知、断点续传等功能。 5. 断点续传: - 如果文件较大,用户可能需要在任何时候暂停或恢复下载。为此,需要...

    Android多线程断点下载源码.zip

    在Android开发中,多线程断点下载是一项重要的技术,尤其在处理大文件时,能够提高下载效率并允许用户在中断后继续下载。这个压缩包"Android多线程断点下载源码.zip"包含了实现这一功能的源代码,对于学习和理解...

    OKHttp断点续传Demo 下载

    本Demo是基于OKHttp3库,并结合RxJava进行封装,实现了断点续传的下载功能。下面我们将详细探讨其中涉及的关键知识点。 首先,`OKHttp`是由Square公司开源的一个高效、强大的HTTP客户端库。它的核心优势在于连接池...

    下载功能工具类.zip

    "下载功能工具类.zip"是一个示例项目,它封装了基于OkHttpClient的下载服务,专门用于处理文件和视频的下载任务,包括断点续传和批量下载等功能。下面我们将深入探讨这些知识点。 首先,`OkHttpClient`是Square公司...

    应用源码之DownLoad(多线程断点续传).zip

    Android系统提供了DownloadManager服务,它支持多线程下载和断点续传。开发者可以通过注册BroadcastReceiver来监听下载进度和完成状态。然而,如果需要更高级的定制,比如自定义下载策略或更细粒度的控制,可能需要...

    Android应用源码之AndroidDownLoad(多线程断点续传).rar

    【标题】"Android应用源码之AndroidDownLoad(多线程断点续传)"是一个针对Android平台的开源项目,旨在实现高效、稳定的文件下载功能,特别是对于大文件,它支持多线程下载和断点续传。这个项目可以帮助开发者深入...

    Android-APP检测升级与下载APP并安装的Android原生API的封装工具类

    4. **下载APK**:使用`DownloadManager` API进行后台下载,这是一个系统服务,可以处理大文件下载且支持断点续传。 5. **安装APK**:下载完成后,利用`Intent`和`ACTION_VIEW`启动安装流程。注意需要设置安装未知...

    android开发 文件上传下载 源码

    2. DownloadManager:Android系统提供的系统服务,能够管理文件下载,并且支持后台下载、断点续传等功能。 3. 自定义下载服务:通过实现Service,配合IntentService或HandlerThread,可以创建一个自定义的下载服务,...

    android 多文件下载

    在实际开发中,我们可以封装一个DownloadManager工具类,它负责管理所有的下载任务,包括创建、暂停、恢复、取消任务,以及处理进度更新。此类应包含以下关键方法: 1. `startDownload(DownloadTask task)`: 启动...

    单、多线程断点续传下载

    例如,`DownloadManager`类是Android系统提供的一个系统服务,支持后台下载、断点续传和通知功能。用户也可以选择第三方库,如Volley、Retrofit或封装好的下载库,如`Android-Universal-Image-Loader`,它们通常集成...

    安卓Android源码——安卓Android快速框架+多线程下载框架的技术.rar

    - 使用DownloadManager API(API 16及以上版本):系统提供的下载服务,支持断点续传和多线程下载。 - 自定义下载框架:可以基于AsyncTask、Handler或RxJava实现,控制线程执行、进度更新和异常处理。 三、Gson库...

    Android实现断点下载的方法

    最近做的项目中需要实现断点下载,即用户一次下载可以分多次进行,下载过程可以中断,在目前大多数的带离线缓存的软件都是需要实现这一功能。本文阐述了通过sqlite3简单实现了一个具有断点下载功能的demo。言归正传...

    Android多线程+单线程+断点续传+进度条显示下载功能

    在Android应用开发中,实现多线程下载、单线程下载、断点续传以及进度条显示是一项常见的需求。以下是对这些知识点的详细说明: **多线程下载**: 多线程下载允许将一个大文件分割成多个小部分,每个部分由一个单独...

Global site tag (gtag.js) - Google Analytics