這篇博客是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