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 size
146      */
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=99
154             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         @Override
173         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/14
12  */
13 public class DBHelper extends SQLiteOpenHelper {
14 
15     public DBHelper(Context context) {
16         super(context, "download.db", null, 1);
17     }
18 
19     @Override
20     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     @Override
28     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 appContent
113      */
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      * @return
138      */
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 url
168      */
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 taskId
111      * @param url
112      * @return
113      */
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 downloadInfo
147      */
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM