最近做的项目中需要实现断点下载,即用户一次下载可以分多次进行,下载过程可以中断,在目前大多数的带离线缓存的软件都是需要实现这一功能。本文阐述了通过sqlite3简单实现了一个具有断点下载功能的demo。言归正传,开始正文。
设计
数据库表存储元数据
DBHelper.java
用于业务存储的Dao
Dao.java
抽象下载信息的Bean
LoadInfo.java
呈现下载信息VIEw
MainActivity.java
存储下载信息Bean
DownloadInfo.java
封装好的下载类
Downloader.java
代码结构
具体实现
下载信息类:DownloadInfo.java
这里的代码很简单,就是一个用来保存下载信息的类,很简单,没啥好说的,具体看注释
package entity;public class DownloadInfo { private int threadID;//线程ID private int startPos;//下载起始位置 private int endPos;//下载结束位置 private int completeSize;//下载完成量 private String url;//资源URL public DownloadInfo(int tID,int sp,int ep,int cSize,String address){ threadID=tID; startPos=sp; endPos=ep; completeSize = cSize; url=address; } /** * @return the threadID */ public int getThreadID() { return threadID; } /** * @param threadID the threadID to set */ public voID setThreadID(int threadID) { this.threadID = threadID; } /** * @return the startPos */ public int getStartPos() { return startPos; } /** * @param startPos the startPos to set */ public voID setStartPos(int startPos) { this.startPos = startPos; } /** * @return the endPos */ public int getEndPos() { return endPos; } /** * @param endPos the endPos to set */ public voID setEndPos(int endPos) { this.endPos = endPos; } /** * @return the completeSize */ public int getCompleteSize() { return completeSize; } /** * @param completeSize the completeSize to set */ public voID setCompleteSize(int completeSize) { this.completeSize = completeSize; } /** * @return the url */ public String getUrl() { return url; } /** * @param url the url to set */ public voID setUrl(String url) { this.url = url; } @OverrIDe public String toString() { // Todo auto-generated method stub return "threadID:"+threadID+",startPos:"+startPos+",endPos:"+endPos+",completeSize:"+completeSize+",url:"+url; }}
数据库 DBHelper.java
package db;import androID.content.Context;import androID.database.sqlite.sqliteDatabase;import androID.database.sqlite.sqliteOpenHelper;public class DBHelper extends sqliteOpenHelper { String sql ="create table download_info (ID integer PRIMARY KEY autoINCREMENT," + "thread_ID integer," + "start_pos integer," + "end_pos integer," + "complete_size integer," + "url char)"; public DBHelper(Context context) { // Todo auto-generated constructor stub super(context,"download.db",null,1); } @OverrIDe public voID onCreate(sqliteDatabase db) { // Todo auto-generated method stub db.execsql(sql); } @OverrIDe public voID onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { // Todo auto-generated method stub }}
数据库业务管理类 Dao.java
package db;import java.util.ArrayList;import java.util.List;import androID.content.Context;import androID.database.Cursor;import androID.database.sqlite.sqliteDatabase;import entity.DownloadInfo;public class Dao { private DBHelper dbHelper; public Dao(Context context){ dbHelper = new DBHelper(context); } public boolean isNewTask(String url){ sqliteDatabase db = dbHelper.getReadableDatabase(); String sql = "select count(*) from download_info where url=?"; Cursor cursor = db.rawquery(sql,new String[]{url}); cursor.movetoFirst(); int count = cursor.getInt(0); cursor.close(); return count == 0; } public voID saveInfo(List<DownloadInfo> infos){ sqliteDatabase db = dbHelper.getWritableDatabase(); String sql = "insert into download_info(thread_ID,start_pos,end_pos,complete_size,url) values(?,?,?)"; Object[] bindArgs= null; for(DownloadInfo info:infos){ bindArgs=new Object[]{info.getThreadID(),info.getStartPos(),info.getEndPos(),info.getCompleteSize(),info.getUrl()}; db.execsql(sql,bindArgs); } } public List<DownloadInfo> getInfo(String url){ sqliteDatabase db = dbHelper.getReadableDatabase(); List<DownloadInfo> infos = new ArrayList<DownloadInfo>(); String sql ="select thread_ID,url from download_info where url=?"; Cursor cursor=db.rawquery(sql,new String[]{url}); while(cursor.movetoNext()){ DownloadInfo info = new DownloadInfo(cursor.getInt(0),cursor.getInt(1),cursor.getInt(2),cursor.getInt(3),cursor.getString(4)); infos.add(info); } cursor.close(); return infos; } public voID deleteInfo(String url){ sqliteDatabase db = dbHelper.getWritableDatabase(); db.delete("download_info","url=?",new String[]{url}); db.close(); } public voID updateInfo(int completeSize,int threadID,String url){ sqliteDatabase db = dbHelper.getWritableDatabase(); String sql ="update download_info set complete_size=? where thread_ID=? and url=?"; db.execsql(sql,new Object[]{completeSize,threadID,url}); } public voID closeDB(){ dbHelper.close(); }}
当前状态保存类 LoadInfo.java
package entity;public class LoadInfo { private int fileSize; private int completeSize; private String url; public LoadInfo(int fs,String address){ fileSize=fs; completeSize = cSize; url=address; } /** * @return the fileSize */ public int getfileSize() { return fileSize; } /** * @param fileSize the fileSize to set */ public voID setfileSize(int fileSize) { this.fileSize = fileSize; } /** * @return the completeSize */ public int getCompleteSize() { return completeSize; } /** * @param completeSize the completeSize to set */ public voID setCompleteSize(int completeSize) { this.completeSize = completeSize; } /** * @return the url */ public String getUrl() { return url; } /** * @param url the url to set */ public voID setUrl(String url) { this.url = url; }}
下载助手类:Downloader.java
package com.winton.downloadmanager;import java.io.file;import java.io.IOException;import java.io.inputStream;import java.io.RandomAccessfile;import java.net.httpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.List;import androID.content.Context;import androID.os.Handler;import androID.os.Message;import db.Dao;import entity.DownloadInfo;import entity.LoadInfo;public class Downloader { private String url; private String localPath; private int threadCount; private Handler mHanler; private Dao dao; private int fileSize; private List<DownloadInfo> infos; private final static int INIT = 1; private final static int DOWNLOADING =2; private final static int PAUSE =3; private int state = INIT; public Downloader(String address,String lPath,int thCount,Context context,Handler handler){ url =address; localPath = lPath; threadCount = thCount; mHanler = handler; dao = new Dao(context); } public boolean isDownloading(){ return state == DOWNLOADING; } public LoadInfo getDownLoadInfos(){ if(isFirstDownload(url)){ init(); int range = fileSize/threadCount; infos = new ArrayList<DownloadInfo>(); for(int i=0;i<=threadCount-1;i++){ DownloadInfo info = new DownloadInfo(i,i*range,(i+1)*range-1,url); infos.add(info); } dao.saveInfo(infos); return new LoadInfo(fileSize,url); }else{ infos = dao.getInfo(url); int size = 0; int completeSize =0; for(DownloadInfo info:infos){ completeSize += info.getCompleteSize(); size += info.getEndPos()-info.getStartPos()+1; } return new LoadInfo(size,completeSize,url); } } public boolean isFirstDownload(String url){ return dao.isNewTask(url); } public voID init(){ try { URL mUrl = new URL(this.url); httpURLConnection connection = (httpURLConnection)mUrl.openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); fileSize = connection.getContentLength(); file file = new file(localPath); if(!file.exists()){ file.createNewfile(); } RandomAccessfile accessfile = new RandomAccessfile(file,"rwd"); accessfile.setLength(fileSize); accessfile.close(); connection.disconnect(); } catch (MalformedURLException e) { // Todo auto-generated catch block e.printstacktrace(); } catch (IOException e) { // Todo auto-generated catch block e.printstacktrace(); } } public voID download(){ if(infos != null){ if(state ==DOWNLOADING){ return; } state = DOWNLOADING; for(DownloadInfo info:infos){ new DownloadThread(info.getThreadID(),info.getUrl()).start(); } } } class DownloadThread extends Thread{ private int threadID; private int startPos; private int endPos; private int completeSize; private String url; public DownloadThread(int tID,String address) { // Todo auto-generated constructor stub threadID=tID; startPos=sp; endPos = ep; completeSize = cSize; url = address; } @OverrIDe public voID run() { // Todo auto-generated method stub httpURLConnection connection = null; RandomAccessfile randomAccessfile = null; inputStream is = null; try { URL mUrl = new URL(url); connection = (httpURLConnection)mUrl.openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); connection.setRequestProperty("Range","bytes="+(startPos+completeSize)+"-"+endPos); randomAccessfile = new RandomAccessfile(localPath,"rwd"); randomAccessfile.seek(startPos+completeSize); is=connection.getinputStream(); byte[] buffer = new byte[4096]; int length =-1; while((length=is.read(buffer)) != -1){ randomAccessfile.write(buffer,length); completeSize +=length; dao.updateInfo(threadID,url); Message msg = Message.obtain(); msg.what=1; msg.obj=url; msg.arg1=length; mHanler.sendMessage(msg); if(state==PAUSE){ return; } } } catch (MalformedURLException e) { // Todo auto-generated catch block e.printstacktrace(); } catch (IOException e) { // Todo auto-generated catch block e.printstacktrace(); }finally{ try { is.close(); randomAccessfile.close(); connection.disconnect(); dao.closeDB(); } catch (IOException e) { // Todo auto-generated catch block e.printstacktrace(); } } } } public voID delete(String url){ dao.deleteInfo(url); } public voID reset(){ state=INIT; } public voID pause(){ state=PAUSE; }}
VIEw呈现类:MainActivity.java
package com.winton.downloadmanager;import androID.app.Activity;import androID.os.Bundle;import androID.os.Environment;import androID.os.Handler;import androID.os.Message;import androID.vIEw.VIEw;import androID.vIEw.VIEw.OnClickListener;import androID.Widget.button;import androID.Widget.Progressbar;import androID.Widget.TextVIEw;import androID.Widget.Toast;import entity.LoadInfo;public class MainActivity extends Activity implements OnClickListener{ private TextVIEw name; private Progressbar process; private button start,stop; private Downloader downloader; //处理下载进度UI的 Handler handler = new Handler(){ public voID handleMessage(androID.os.Message msg) { if(msg.what==1){ name.setText((String)msg.obj); int lenght = msg.arg1; process.incrementProgressBy(lenght); } if(msg.what==2){ int max =msg.arg1; process.setMax(max); Toast.makeText(getApplicationContext(),max+"",1).show(); } }; }; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); name=(TextVIEw)findVIEwByID(R.ID.tv_name); process=(Progressbar)findVIEwByID(R.ID.pb_download); start = (button)findVIEwByID(R.ID.bt_start); stop = (button)findVIEwByID(R.ID.bt_stop); start.setonClickListener(this); stop.setonClickListener(this); downloader=new Downloader("http://img4.duitang.com/uploads/item/201206/11/20120611174542_5KRMj.jpeg",Environment.getExternalStorageDirectory().getPath()+"/test1.jpg",1,getApplicationContext(),handler); } @OverrIDe public voID onClick(VIEw v) { // Todo auto-generated method stub if(v==start){ new Thread(new Runnable() { @OverrIDe public voID run() { // Todo auto-generated method stub LoadInfo loadInfo = downloader.getDownLoadInfos(); Message msg =handler.obtainMessage(); msg.what=2; msg.arg1=loadInfo.getfileSize(); handler.sendMessage(msg); downloader.download(); } }).start(); return; } if(v==stop){ downloader.pause(); return; } } }
运行效果
总体比较简单,基本实现了 断点下载的功能,而且开启了多个线程去实现分块下载,对初学的同学有一定的帮助。
这些代码我也是从网上各种搜集而来,自己亲自动手敲了一遍,并做了一些小的改动,对整个断点下载的过程有了一个深刻的认识。因此平时要多敲代码,善于总结,必能有所收获。
总结以上是内存溢出为你收集整理的Android实现断点下载的方法全部内容,希望文章能够帮你解决Android实现断点下载的方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)