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