你的位置:首页 > 操作系统

[操作系统]AsyncTask实现多任务多线程断点续传下载


  这篇博客是AsyncTask下载系列的最后一篇文章,前面写了关于断点续传的和多线程下载的博客,这篇是在前两篇的基础上面实现的,有兴趣的可以去看下。

  一、AsyncTask实现断点续传

  二、AsyncTask实现多线程断点续传

  这里模拟应用市场app下载实现了一个Demo,因为只有一个界面,所以没有将下载放到Service中,而是直接在Activity中创建。在正式的项目中,下载都是放到Service中,然后通过BroadCast通知界面更新进度。

  上代码之前,先看下demo的运行效果图吧。

 

  下面我们看代码,这里每一个文件的下载定义一个Downloador来管理下载该文件的所有线程(暂停、下载等)。Downloador创建3个DownloadTask(这里定义每个文件分配3个线程下载)来下载该文件特定的起止位置。这里要通过文件的大小来计算每个线程所下载的起止位置,详细可以参考《AsyncTask实现多线程断点续传》。

  1、Downloador类

 1 package com.bbk.lling.multitaskdownload.downloador; 2  3 import android.content.Context; 4 import android.content.Intent; 5 import android.os.AsyncTask; 6 import android.os.Bundle; 7 import android.os.Handler; 8 import android.os.Message; 9 import android.text.TextUtils; 10 import android.util.Log; 11 import android.widget.Toast; 12  13 import com.bbk.lling.multitaskdownload.beans.AppContent; 14 import com.bbk.lling.multitaskdownload.beans.DownloadInfo; 15 import com.bbk.lling.multitaskdownload.db.DownloadFileDAO; 16 import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO; 17 import com.bbk.lling.multitaskdownload.utils.DownloadUtils; 18  19 import org.apache.http.HttpResponse; 20 import org.apache.http.client.HttpClient; 21 import org.apache.http.client.methods.HttpGet; 22 import org.apache.http.impl.client.DefaultHttpClient; 23  24 import java.util.ArrayList; 25 import java.util.List; 26 import java.util.concurrent.Executor; 27 import java.util.concurrent.Executors; 28  29 /** 30  * @Class: Downloador 31  * @Description: 任务下载器 32  * @author: lling(www.cnblogs.com/liuling) 33  * @Date: 2015/10/13 34 */ 35 public class Downloador { 36   public static final String TAG = "Downloador"; 37   private static final int THREAD_POOL_SIZE = 9; //线程池大小为9 38   private static final int THREAD_NUM = 3; //每个文件3个线程下载 39   private static final int GET_LENGTH_SUCCESS = 1; 40   public static final Executor THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(THREAD_POOL_SIZE); 41  42   private List<DownloadTask> tasks; 43   private InnerHandler handler = new InnerHandler(); 44  45   private AppContent appContent; //待下载的应用 46   private long downloadLength; //下载过程中记录已下载大小 47   private long fileLength; 48   private Context context; 49   private String downloadPath; 50  51   public Downloador(Context context, AppContent appContent) { 52     this.context = context; 53     this.appContent = appContent; 54     this.downloadPath = DownloadUtils.getDownloadPath(); 55   } 56  57   /** 58    * 开始下载 59   */ 60   public void download() { 61     if(TextUtils.isEmpty(downloadPath)) { 62       Toast.makeText(context, "未找到SD卡", Toast.LENGTH_SHORT).show(); 63       return; 64     } 65     if(appContent == null) { 66       throw new IllegalArgumentException("download content can not be null"); 67     } 68     new Thread() { 69       @Override 70       public void run() { 71         //获取文件大小 72         HttpClient client = new DefaultHttpClient(); 73         HttpGet request = new HttpGet(appContent.getUrl()); 74         HttpResponse response = null; 75         try { 76           response = client.execute(request); 77           fileLength = response.getEntity().getContentLength(); 78         } catch (Exception e) { 79           Log.e(TAG, e.getMessage()); 80         } finally { 81           if (request != null) { 82             request.abort(); 83           } 84         } 85         //计算出该文件已经下载的总长度 86         List<DownloadInfo> lists = DownloadInfoDAO.getInstance(context.getApplicationContext()) 87             .getDownloadInfosByUrl(appContent.getUrl()); 88         for (DownloadInfo info : lists) { 89           downloadLength += info.getDownloadLength(); 90         } 91  92         //插入文件下载记录到数据库 93         DownloadFileDAO.getInstance(context.getApplicationContext()).insertDownloadFile(appContent); 94         Message.obtain(handler, GET_LENGTH_SUCCESS).sendToTarget(); 95       } 96     }.start(); 97   } 98  99   /**100    * 开始创建AsyncTask下载101   */102   private void beginDownload() {103     Log.e(TAG, "beginDownload" + appContent.getUrl());104     appContent.setStatus(AppContent.Status.WAITING);105     long blockLength = fileLength / THREAD_NUM;106     for (int i = 0; i < THREAD_NUM; i++) {107       long beginPosition = i * blockLength;//每条线程下载的开始位置108       long endPosition = (i + 1) * blockLength;//每条线程下载的结束位置109       if (i == (THREAD_NUM - 1)) {110         endPosition = fileLength;//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度111       }112       DownloadTask task = new DownloadTask(i, beginPosition, endPosition, this, context);113       task.executeOnExecutor(THREAD_POOL_EXECUTOR, appContent.getUrl());114       if(tasks == null) {115         tasks = new ArrayList<DownloadTask>();116       }117       tasks.add(task);118     }119   }120 121   /**122    * 暂停下载123   */124   public void pause() {125     for (DownloadTask task : tasks) {126       if (task != null && (task.getStatus() == AsyncTask.Status.RUNNING || !task.isCancelled())) {127         task.cancel(true);128       }129     }130     tasks.clear();131     appContent.setStatus(AppContent.Status.PAUSED);132     DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);133   }134 135   /**136    * 将已下载大小归零137   */138   protected synchronized void resetDownloadLength() {139     this.downloadLength = 0;140   }141 142   /**143    * 添加已下载大小144    * 多线程访问需加锁145    * @param size146   */147   protected synchronized void updateDownloadLength(long size){148     this.downloadLength += size;149     //通知更新界面150     int percent = (int)((float)downloadLength * 100 / (float)fileLength);151     appContent.setDownloadPercent(percent);152     if(percent == 100 || downloadLength == fileLength) {153       appContent.setDownloadPercent(100); //上面计算有时候会有点误差,算到percent=99154       appContent.setStatus(AppContent.Status.FINISHED);155       DownloadFileDAO.getInstance(context.getApplicationContext()).updateDownloadFile(appContent);156     }157     Intent intent = new Intent(Constants.DOWNLOAD_MSG);158     if(appContent.getStatus() == AppContent.Status.WAITING) {159       appContent.setStatus(AppContent.Status.DOWNLOADING);160     }161     Bundle bundle = new Bundle();162     bundle.putParcelable("appContent", appContent);163     intent.putExtras(bundle);164     context.sendBroadcast(intent);165   }166 167   protected String getDownloadPath() {168     return downloadPath;169   }170 171   private class InnerHandler extends Handler {172     @Override173     public void handleMessage(Message msg) {174       switch (msg.what) {175         case GET_LENGTH_SUCCESS :176           beginDownload();177           break;178       }179       super.handleMessage(msg);180     }181   }182 }

  2、DownloadTask类

 1 package com.bbk.lling.multitaskdownload.downloador; 2  3 import android.content.Context; 4 import android.os.AsyncTask; 5 import android.util.Log; 6  7 import com.bbk.lling.multitaskdownload.beans.DownloadInfo; 8 import com.bbk.lling.multitaskdownload.db.DownloadInfoDAO; 9  10 import org.apache.http.Header; 11 import org.apache.http.HttpResponse; 12 import org.apache.http.client.HttpClient; 13 import org.apache.http.client.methods.HttpGet; 14 import org.apache.http.impl.client.DefaultHttpClient; 15 import org.apache.http.message.BasicHeader; 16  17 import java.io.File; 18 import java.io.IOException; 19 import java.io.InputStream; 20 import java.io.OutputStream; 21 import java.io.RandomAccessFile; 22 import java.net.MalformedURLException; 23  24 /** 25  * @Class: DownloadTask 26  * @Description: 文件下载AsyncTask 27  * @author: lling(www.cnblogs.com/liuling) 28  * @Date: 2015/10/13 29 */ 30 public class DownloadTask extends AsyncTask<String, Integer , Long> { 31   private static final String TAG = "DownloadTask"; 32  33   private int taskId; 34   private long beginPosition; 35   private long endPosition; 36   private long downloadLength; 37   private String url; 38   private Downloador downloador; 39   private DownloadInfoDAO downloadInfoDAO; 40  41  42   public DownloadTask(int taskId, long beginPosition, long endPosition, Downloador downloador, 43             Context context) { 44     this.taskId = taskId; 45     this.beginPosition = beginPosition; 46     this.endPosition = endPosition; 47     this.downloador = downloador; 48     downloadInfoDAO = DownloadInfoDAO.getInstance(context.getApplicationContext()); 49   } 50  51   @Override 52   protected void onPreExecute() { 53     Log.e(TAG, "onPreExecute"); 54   } 55  56   @Override 57   protected void onPostExecute(Long aLong) { 58     Log.e(TAG, url + "taskId:" + taskId + "executed"); 59 //    downloador.updateDownloadInfo(null); 60   } 61  62   @Override 63   protected void onProgressUpdate(Integer... values) { 64     //通知downloador增加已下载大小 65 //    downloador.updateDownloadLength(values[0]); 66   } 67  68   @Override 69   protected void onCancelled() { 70     Log.e(TAG, "onCancelled"); 71 //    downloador.updateDownloadInfo(null); 72   } 73  74   @Override 75   protected Long doInBackground(String... params) { 76     //这里加判断的作用是:如果还处于等待就暂停了,运行到这里已经cancel了,就直接退出 77     if(isCancelled()) { 78       return null; 79     } 80     url = params[0]; 81     if(url == null) { 82       return null; 83     } 84     HttpClient client = new DefaultHttpClient(); 85     HttpGet request = new HttpGet(url); 86     HttpResponse response; 87     InputStream is; 88     RandomAccessFile fos = null; 89     OutputStream output = null; 90  91     DownloadInfo downloadInfo = null; 92     try { 93       //本地文件 94       File file = new File(downloador.getDownloadPath() + File.separator + url.substring(url.lastIndexOf("/") + 1)); 95  96       //获取之前下载保存的信息 97       downloadInfo = downloadInfoDAO.getDownloadInfoByTaskIdAndUrl(taskId, url); 98       //从之前结束的位置继续下载 99       //这里加了判断file.exists(),判断是否被用户删除了,如果文件没有下载完,但是已经被用户删除了,则重新下载100       if(file.exists() && downloadInfo != null) {101         if(downloadInfo.isDownloadSuccess() == 1) {102           //下载完成直接结束103           return null;104         }105         beginPosition = beginPosition + downloadInfo.getDownloadLength();106         downloadLength = downloadInfo.getDownloadLength();107       }108       if(!file.exists()) {109         //如果此task已经下载完,但是文件被用户删除,则需要重新设置已下载长度,重新下载110         downloador.resetDownloadLength();111       }112 113       //设置下载的数据位置beginPosition字节到endPosition字节114       Header header_size = new BasicHeader("Range", "bytes=" + beginPosition + "-" + endPosition);115       request.addHeader(header_size);116       //执行请求获取下载输入流117       response = client.execute(request);118       is = response.getEntity().getContent();119 120       //创建文件输出流121       fos = new RandomAccessFile(file, "rw");122       //从文件的size以后的位置开始写入123       fos.seek(beginPosition);124 125       byte buffer [] = new byte[1024];126       int inputSize = -1;127       while((inputSize = is.read(buffer)) != -1) {128         fos.write(buffer, 0, inputSize);129         downloadLength += inputSize;130         downloador.updateDownloadLength(inputSize);131 132         //如果暂停了,需要将下载信息存入数据库133         if (isCancelled()) {134           if(downloadInfo == null) {135             downloadInfo = new DownloadInfo();136           }137           downloadInfo.setUrl(url);138           downloadInfo.setDownloadLength(downloadLength);139           downloadInfo.setTaskId(taskId);140           downloadInfo.setDownloadSuccess(0);141           //保存下载信息到数据库142           downloadInfoDAO.insertDownloadInfo(downloadInfo);143           return null;144         }145       }146     } catch (MalformedURLException e) {147       Log.e(TAG, e.getMessage());148     } catch (IOException e) {149       Log.e(TAG, e.getMessage());150     } finally{151       try{152         if (request != null) {153           request.abort();154         }155         if(output != null) {156           output.close();157         }158         if(fos != null) {159           fos.close();160         }161       } catch(Exception e) {162         e.printStackTrace();163       }164     }165     //执行到这里,说明该task已经下载完了166     if(downloadInfo == null) {167       downloadInfo = new DownloadInfo();168     }169     downloadInfo.setUrl(url);170     downloadInfo.setDownloadLength(downloadLength);171     downloadInfo.setTaskId(taskId);172     downloadInfo.setDownloadSuccess(1);173     //保存下载信息到数据库174     downloadInfoDAO.insertDownloadInfo(downloadInfo);175     return null;176   }177 }

  Downloador和DownloadTask只这个例子的核心代码,下面是关于数据库的,因为要实现断点续传必须要在暂停的时候将每个线程下载的位置记录下来,方便下次继续下载时读取。这里有两个表,一个是存放每个文件的下载状态的,一个是存放每个文件对应的每个线程的下载状态的。

  3、DBHelper

 1 package com.bbk.lling.multitaskdownload.db; 2  3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteOpenHelper; 6  7 /** 8  * @Class: DBHelper 9  * @Description: 数据库帮助类10  * @author: lling(www.cnblogs.com/liuling)11  * @Date: 2015/10/1412 */13 public class DBHelper extends SQLiteOpenHelper {14 15   public DBHelper(Context context) {16     super(context, "download.db", null, 1);17   }18 19   @Override20   public void onCreate(SQLiteDatabase db) {21     db.execSQL("create table download_info(_id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER, "22         + "download_length INTEGER, url VARCHAR(255), is_success INTEGER)");23     db.execSQL("create table download_file(_id INTEGER PRIMARY KEY AUTOINCREMENT, app_name VARCHAR(255), "24         + "url VARCHAR(255), download_percent INTEGER, status INTEGER)");25   }26 27   @Override28   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {29 30   }31 }

  4、DownloadFileDAO,文件下载状态的数据库操作类

 1 package com.bbk.lling.multitaskdownload.db; 2  3 import android.content.Context; 4 import android.database.Cursor; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.text.TextUtils; 7 import android.util.Log; 8  9 import com.bbk.lling.multitaskdownload.beans.AppContent; 10  11 import java.util.ArrayList; 12 import java.util.List; 13  14 /** 15  * @Class: DownloadFileDAO 16  * @Description: 每个文件下载状态记录的数据库操作类 17  * @author: lling(www.cnblogs.com/liuling) 18  * @Date: 2015/10/13 19 */ 20 public class DownloadFileDAO { 21   private static final String TAG = "DownloadFileDAO"; 22   private static DownloadFileDAO dao=null; 23   private Context context; 24   private DownloadFileDAO(Context context) { 25     this.context=context; 26   } 27  28   synchronized public static DownloadFileDAO getInstance(Context context){ 29     if(dao==null){ 30       dao=new DownloadFileDAO(context); 31     } 32     return dao; 33   } 34  35   /** 36    * 获取数据库连接 37    * @return 38   */ 39   public SQLiteDatabase getConnection() { 40     SQLiteDatabase sqliteDatabase = null; 41     try { 42       sqliteDatabase= new DBHelper(context).getReadableDatabase(); 43     } catch (Exception e) { 44       Log.e(TAG, e.getMessage()); 45     } 46     return sqliteDatabase; 47   } 48  49   /** 50    * 插入数据 51    * @param appContent 52   */ 53   public void insertDownloadFile(AppContent appContent) { 54     if(appContent == null) { 55       return; 56     } 57     //如果本地已经存在,直接修改 58     if(getAppContentByUrl(appContent.getUrl()) != null) { 59       updateDownloadFile(appContent); 60       return; 61     } 62     SQLiteDatabase database = getConnection(); 63     try { 64       String sql = "insert into download_file(app_name, url, download_percent, status) values (?,?,?,?)"; 65       Object[] bindArgs = { appContent.getName(), appContent.getUrl(), appContent.getDownloadPercent() 66           , appContent.getStatus().getValue()}; 67       database.execSQL(sql, bindArgs); 68     } catch (Exception e) { 69       Log.e(TAG, e.getMessage()); 70     } finally { 71       if (null != database) { 72         database.close(); 73       } 74     } 75   } 76  77   /** 78    * 根据url获取下载文件信息 79    * @param url 80    * @return 81   */ 82   public AppContent getAppContentByUrl(String url) { 83     if(TextUtils.isEmpty(url)) { 84       return null; 85     } 86     SQLiteDatabase database = getConnection(); 87     AppContent appContent = null; 88     Cursor cursor = null; 89     try { 90       String sql = "select * from download_file where url=?"; 91       cursor = database.rawQuery(sql, new String[] { url }); 92       if (cursor.moveToNext()) { 93         appContent = new AppContent(cursor.getString(1), cursor.getString(2)); 94         appContent.setDownloadPercent(cursor.getInt(3)); 95         appContent.setStatus(AppContent.Status.getByValue(cursor.getInt(4))); 96       } 97     } catch (Exception e) { 98       Log.e(TAG, e.getMessage()); 99     } finally {100       if (null != database) {101         database.close();102       }103       if (null != cursor) {104         cursor.close();105       }106     }107     return appContent;108   }109 110   /**111    * 更新下载信息112    * @param appContent113   */114   public void updateDownloadFile(AppContent appContent) {115     if(appContent == null) {116       return;117     }118     SQLiteDatabase database = getConnection();119     try {120       Log.e(TAG, "update download_file,app name:" + appContent.getName() + ",url:" + appContent.getUrl()121           + ",percent" + appContent.getDownloadPercent() + ",status:" + appContent.getStatus().getValue());122       String sql = "update download_file set app_name=?, url=?, download_percent=?, status=? where url=?";123       Object[] bindArgs = {appContent.getName(), appContent.getUrl(), appContent.getDownloadPercent()124           , appContent.getStatus().getValue(), appContent.getUrl()};125       database.execSQL(sql, bindArgs);126     } catch (Exception e) {127       Log.e(TAG, e.getMessage());128     } finally {129       if (null != database) {130         database.close();131       }132     }133   }134 135   /**136    * 获取所有下载文件记录137    * @return138   */139   public List<AppContent> getAll() {140     SQLiteDatabase database = getConnection();141     List<AppContent> list = new ArrayList<AppContent>();142     Cursor cursor = null;143     try {144       String sql = "select * from download_file";145       cursor = database.rawQuery(sql, null);146       while (cursor.moveToNext()) {147         AppContent appContent = new AppContent(cursor.getString(1), cursor.getString(2));148         appContent.setDownloadPercent(cursor.getInt(3));149         appContent.setStatus(AppContent.Status.getByValue(cursor.getInt(4)));150         list.add(appContent);151       }152     } catch (Exception e) {153       Log.e(TAG, e.getMessage());154     } finally {155       if (null != database) {156         database.close();157       }158       if (null != cursor) {159         cursor.close();160       }161     }162     return list;163   }164 165   /**166    * 根据url删除记录167    * @param url168   */169   public void delByUrl(String url) {170     if(TextUtils.isEmpty(url)) {171       return;172     }173     SQLiteDatabase database = getConnection();174     try {175       String sql = "delete from download_file where url=?";176       Object[] bindArgs = { url };177       database.execSQL(sql, bindArgs);178     } catch (Exception e) {179       Log.e(TAG, e.getMessage());180     } finally {181       if (null != database) {182         database.close();183       }184     }185   }186 187 }

  5、DownloadInfoDAO,每个线程对应下载状态的数据库操作类

 1 package com.bbk.lling.multitaskdownload.db; 2  3 import android.content.Context; 4 import android.database.Cursor; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.text.TextUtils; 7 import android.util.Log; 8  9 import com.bbk.lling.multitaskdownload.beans.DownloadInfo; 10  11 import java.util.ArrayList; 12 import java.util.List; 13  14 /** 15  * @Class: DownloadInfoDAO 16  * @Description: 每个单独线程下载信息记录的数据库操作类 17  * @author: lling(www.cnblogs.com/liuling) 18  * @Date: 2015/10/13 19 */ 20 public class DownloadInfoDAO { 21   private static final String TAG = "DownloadInfoDAO"; 22   private static DownloadInfoDAO dao=null; 23   private Context context; 24   private DownloadInfoDAO(Context context) { 25     this.context=context; 26   } 27  28   synchronized public static DownloadInfoDAO getInstance(Context context){ 29     if(dao==null){ 30       dao=new DownloadInfoDAO(context); 31     } 32     return dao; 33   } 34  35   /** 36    * 获取数据库连接 37    * @return 38   */ 39   public SQLiteDatabase getConnection() { 40     SQLiteDatabase sqliteDatabase = null; 41     try { 42       sqliteDatabase= new DBHelper(context).getReadableDatabase(); 43     } catch (Exception e) { 44       Log.e(TAG, e.getMessage()); 45     } 46     return sqliteDatabase; 47   } 48  49   /** 50    * 插入数据 51    * @param downloadInfo 52   */ 53   public void insertDownloadInfo(DownloadInfo downloadInfo) { 54     if(downloadInfo == null) { 55       return; 56     } 57     //如果本地已经存在,直接修改 58     if(getDownloadInfoByTaskIdAndUrl(downloadInfo.getTaskId(), downloadInfo.getUrl()) != null) { 59       updateDownloadInfo(downloadInfo); 60       return; 61     } 62     SQLiteDatabase database = getConnection(); 63     try { 64       String sql = "insert into download_info(task_id, download_length, url, is_success) values (?,?,?,?)"; 65       Object[] bindArgs = { downloadInfo.getTaskId(), downloadInfo.getDownloadLength(), 66           downloadInfo.getUrl(), downloadInfo.isDownloadSuccess()}; 67       database.execSQL(sql, bindArgs); 68     } catch (Exception e) { 69       Log.e(TAG, e.getMessage()); 70     } finally { 71       if (null != database) { 72         database.close(); 73       } 74     } 75   } 76  77   public List<DownloadInfo> getDownloadInfosByUrl(String url) { 78     if(TextUtils.isEmpty(url)) { 79       return null; 80     } 81     SQLiteDatabase database = getConnection(); 82     List<DownloadInfo> list = new ArrayList<DownloadInfo>(); 83     Cursor cursor = null; 84     try { 85       String sql = "select * from download_info where url=?"; 86       cursor = database.rawQuery(sql, new String[] { url }); 87       while (cursor.moveToNext()) { 88         DownloadInfo info = new DownloadInfo(); 89         info.setTaskId(cursor.getInt(1)); 90         info.setDownloadLength(cursor.getLong(2)); 91         info.setDownloadSuccess(cursor.getInt(4)); 92         info.setUrl(cursor.getString(3)); 93         list.add(info); 94       } 95     } catch (Exception e) { 96       e.printStackTrace(); 97     } finally { 98       if (null != database) { 99         database.close();100       }101       if (null != cursor) {102         cursor.close();103       }104     }105     return list;106   }107 108   /**109    * 根据taskid和url获取下载信息110    * @param taskId111    * @param url112    * @return113   */114   public DownloadInfo getDownloadInfoByTaskIdAndUrl(int taskId, String url) {115     if(TextUtils.isEmpty(url)) {116       return null;117     }118     SQLiteDatabase database = getConnection();119     DownloadInfo info = null;120     Cursor cursor = null;121     try {122       String sql = "select * from download_info where url=? and task_id=?";123       cursor = database.rawQuery(sql, new String[] { url, String.valueOf(taskId) });124       if (cursor.moveToNext()) {125         info = new DownloadInfo();126         info.setTaskId(cursor.getInt(1));127         info.setDownloadLength(cursor.getLong(2));128         info.setDownloadSuccess(cursor.getInt(4));129         info.setUrl(cursor.getString(3));130       }131     } catch (Exception e) {132       Log.e(TAG, e.getMessage());133     } finally {134       if (null != database) {135         database.close();136       }137       if (null != cursor) {138         cursor.close();139       }140     }141     return info;142   }143 144   /**145    * 更新下载信息146    * @param downloadInfo147   */148   public void updateDownloadInfo(DownloadInfo downloadInfo) {149     if(downloadInfo == null) {150       return;151     }152     SQLiteDatabase database = getConnection();153     try {154       String sql = "update download_info set download_length=?, is_success=? where task_id=? and url=?";155       Object[] bindArgs = { downloadInfo.getDownloadLength(), downloadInfo.isDownloadSuccess(),156           downloadInfo.getTaskId(), downloadInfo.getUrl() };157       database.execSQL(sql, bindArgs);158     } catch (Exception e) {159       Log.e(TAG, e.getMessage());160     } finally {161       if (null != database) {162         database.close();163       }164     }165   }166 167 }

  具体的界面和使用代码我就不贴代码了,代码有点多。需要的可以下载Demo的源码看看。

  因为还没有花太多时间去测,里面难免会有些bug,如果大家发现什么问题,欢迎留言探讨,谢谢!

  

源码下载:https://github.com/liuling07/MultiTaskAndThreadDownload

 

原创内容,转载请注明出处:http://www.cnblogs.com/liuling/p/2015-10-16-01.html