本文实例为大家分享了android实现多线程断点续传的具体代码,供大家参考,具体内容如下
多线程下载涉及到的知识点:
1、service的使用:我们在service中去下载文件;
2、thread的使用:service本身不支持耗时操作,所以我们要去开启线程;
3、sqlite的使用:使用数据库来存储每个线程下载的文件的进度,和文件的下载情况;
4、权限:涉及到文件的读写就要用到权限;
5、broadcastreceiver的使用:通过广播来更新下载进度;
6、线程池使用:使用线程池来管理线程,减少资源的浪费
7、httpurlconnection的使用:下载文件使用的
8、listview和baseadapter的使用:下载列表的显示
9、randomaccessfile使用
先解释一下我们要做什么:
1、我们现在有一个文件,然后要分成好几个线程去下载,那么我们需要将这个文件平分,然后分给各个线程去下载,而每个线程在下载的时候,你不一定啥时候点了暂停,那么就要记录我的下载进度,所以要用到数据库 。
2、你可能又会问,怎么去知道谁下载哪呢?我们的httpurlconnection可以通过他的setrequestproperty()方法设置下载范围,从哪开始到哪结束 。
3、同样下载解决了,那么写文件呢,怎么往文件里面写呢,那么就要用到randomaccessfile这个文件的特性了,从文件的任意位置开始写,是不是清晰了 。
4、 还有问题就是怎么更新界面,用我们的广播,告诉什么时候去更新界面 。
(实现的效果,是一个文件可以由多个线程下载,可以同时下载多个文件)
**这里需要注意:**不可以在获取长度后直接去下载文件,因为,我们获取文件长度的时候需要使用的请求码是200,如果我们想要分段去下载(也就是设置了connection.setrequestproperty(“range”,“bytes=”"之后就是分段下载了)那么使用到的请求码是206 。所以我们这里要将这两个请求分开来写,我就一开始将两个写到一起了,但是是不可以的会报错,更不要想着通过请求码来区分,这个就更错了
1、下面贴出***服务类***的代码:
这里的工作主要就是开启下载任务和停止下载任务,还有就是获取下载文件的长度,并创建本地文件并设置长度 。
public class downloadservice extends service { public static final int status_start = 0; public static final int status_stop = 1; public static final string path = environment.getexternalstoragedirectory().getabsolutepath(); private fileinfo mfileinfo; //统一管理downloadtask,有个文件下载就有个downloadtask,所以使用map去管理,主要控制暂停 private map<integer,object> downtaskmap = new hashmap<>(); private downloadtask downloadtask; @override public void oncreate() { super.oncreate(); } @override public int onstartcommand(intent intent, int flags, int startid) { if (intent != null) { int status = intent.getintextra("status", 0); if (status == status_start) { //开始下载 mfileinfo = (fileinfo) intent.getserializableextra("fileinfo"); downloadtask.sexecutorservice.execute(new getfilelenght(mfileinfo, this)); } else { //暂停下载 mfileinfo = (fileinfo) intent.getserializableextra("fileinfo"); log.e("---------->","mfileinfo:"+mfileinfo); downloadtask = (downloadtask) downtaskmap.get(mfileinfo.getid()); if(downloadtask!=null){ downloadtask.ispause = true; } } } return super.onstartcommand(intent, flags, startid); } @nullable @override public ibinder onbind(intent intent) { return null; } /** * 获得要下载的文件的长度,并创建本地文件 * 不能和下载的线程写在一起 */ class getfilelenght extends thread { private fileinfo fileinfo; private context context; public getfilelenght(fileinfo fileinfo, context context) { this.fileinfo = fileinfo; this.context = context; } @override public void run() { super.run(); httpurlconnection conn = null; randomaccessfile raf = null; try { url url = new url(fileinfo.geturl()); conn = (httpurlconnection) url.openconnection(); conn.setconnecttimeout(5000); conn.setrequestmethod("get"); int length = -1; if (conn.getresponsecode() == 200) { length = conn.getcontentlength(); if (length > 0) { //创建本地文件 file file = new file(path, fileinfo.getfile_name()); raf = new randomaccessfile(file, "rwd"); //设置本地文件的长度 raf.setlength(length); fileinfo.setlength(length); //开始下载 downloadtask =new downloadtask(downloadservice.this,fileinfo); downloadtask.down(); downtaskmap.put(fileinfo.getid(),downloadtask); } } } catch (exception e) { e.printstacktrace(); } finally { conn.disconnect(); try { if (raf != null) { raf.close(); } } catch (ioexception e) { e.printstacktrace(); } } } }}2、downloadtask的代码,也就是真正的核心的地方
这里的关系是一个fileinfo对应一个downloadtask,一个downloadtask对应着多个线程
package com.example.a_0102.mylearn.download;import android.content.context;import android.content.intent;import android.util.log;import java.io.file;import java.io.ioexception;import java.io.inputstream;import java.io.randomaccessfile;import java.net.httpurlconnection;import java.net.url;import java.util.arraylist;import java.util.list;import java.util.concurrent.executorservice;import java.util.concurrent.executors;/** * 下载文件的内容 */public class downloadtask { private context context; private fileinfo fileinfo; private int countforthread = 3;//线程的数量 private int mfinished; private downloadtaskimpl downloadtask; private list<threadinfo> threadinfos; private list<downloadthread> downloadthreads; public boolean ispause = false; public static executorservice sexecutorservice = executors.newcachedthreadpool();//共用一个线程池 public downloadtask(context context,fileinfo fileinfo) { this.fileinfo = fileinfo; this.context = context; downloadtask = new downloadtaskimpl(context); } public void down(){ threadinfos = downloadtask.getthreadinfos(fileinfo.geturl()); if(threadinfos.size() == 0){ mfinished = 0; //计算每个线程应下载的长度 int every_length = fileinfo.getlength()/countforthread; for(int i = 0;i<countforthread;i++){ threadinfo threadinfo = new threadinfo(); threadinfo.setstart_flag(i*every_length); threadinfo.setend_flag((i+1)*every_length-1); threadinfo.setfinished(0); threadinfo.seturl(fileinfo.geturl()); threadinfo.setthread_id(i); //可能不能平分,最后一个线程的长度为剩余的所有 if(i == countforthread-1){ threadinfo.setend_flag(fileinfo.getlength()); } downloadtask.insertthreadinfo(threadinfo); threadinfos.add(threadinfo); } }else { //该文件一共下载了多少了 mfinished = fileinfo.getfinished(); } downloadthreads = new arraylist<>(); downloadthread downloadthread = null; for(int i = 0;i<threadinfos.size();i++){ downloadthread = new downloadthread(threadinfos.get(i));// downloadthread.start(); downloadtask.sexecutorservice.execute(downloadthread);//执行线程,相当于开启个线程使用这个就不需要使用.start方法 downloadthreads.add(downloadthread); } } //真正开始下载文件的线程 class downloadthread extends thread{ private threadinfo threadinfo; private boolean isfinished;//该线程是否结束 public downloadthread(threadinfo threadinfo) { this.threadinfo = threadinfo; log.e("------------->","threadinfo:"+threadinfo); } @override public void run() { super.run(); httpurlconnection connection = null; randomaccessfile accessfile = null; inputstream inputstream = null; intent intent = new intent(); intent.setaction("update_progressbar"); try { url url = new url(threadinfo.geturl()); connection = (httpurlconnection) url.openconnection(); connection.setrequestmethod("get"); connection.setconnecttimeout(5000); //下载开始的范围是,这个线程的开始下载的地方+已经下载的进度 long start = threadinfo.getstart_flag()+threadinfo.getfinished(); //设置下载的范围 connection.setrequestproperty("range","bytes="+start+"-"+threadinfo.getend_flag()); file file = new file(downloadservice.path,fileinfo.getfile_name()); accessfile = new randomaccessfile(file,"rwd"); //设置文件写入位置 accessfile.seek(start); int len = -1; byte[] bytes = new byte[1024]; if(connection.getresponsecode() == 206){ inputstream = connection.getinputstream(); long time = system.currenttimemillis(); while ((len = inputstream.read(bytes))!=-1){ accessfile.write(bytes,0,len); //文件整体的下载进度 mfinished+=len; threadinfo.setfinished(threadinfo.getfinished()+len); //每1秒钟发送一个广播更新界面 if(system.currenttimemillis()-time>1000){ time = system.currenttimemillis(); //以便区分下载的是那个文件 intent.putextra("id",fileinfo.getid()); intent.putextra("length",fileinfo.getlength()); intent.putextra("finished",mfinished); context.sendbroadcast(intent); } //暂停更新数据库 if(ispause){ downloadtask.updatethreadinfo(threadinfo,threadinfo.getthread_id(),threadinfo.geturl()); return; } } log.e("------------>","线程结束:"+threadinfo.tostring()); isfinished = true; downloadtask.updatethreadinfo(threadinfo,threadinfo.getthread_id(),threadinfo.geturl()); checkallthreadfinish(); } } catch (exception e) { e.printstacktrace(); }finally { connection.disconnect(); if(inputstream!=null){ try { inputstream.close(); accessfile.close(); } catch (ioexception e) { e.printstacktrace(); } } } } //所有的线程下载完成 private synchronized void checkallthreadfinish(){ boolean finishall = true; for(downloadthread downloadthread:downloadthreads){ if(!downloadthread.isfinished){ finishall = false; return; } } if(finishall){ downloadtask.deletethreadinfo(fileinfo.geturl()); //有些时候可能刚好下完,但是那1秒的时候没有取到所以进度可能停在97%,所以这样处理保证视觉的效果,可以直接将mfinished替换为fileinfo.getlength() 。 intent intent = new intent(); intent.setaction("update_progressbar"); intent.putextra("id",fileinfo.getid()); intent.putextra("length",fileinfo.getlength()); intent.putextra("finished",mfinished); context.sendbroadcast(intent); } } }}3、界面的代码
上面罗列知识点的时候,说到了权限,如果手机系统是6.0 以上的要获取权限即请求用户允许的那种,否则会出现android.system.errnoexception: open failed: eacces (permission denied)异常,下面代码中涉及权限的就是模拟一下,具体逻辑没有严格的去实现,大家看的时候需要注意 。。
package com.example.a_0102.mylearn.download;import android.content.broadcastreceiver;import android.content.context;import android.content.intent;import android.content.intentfilter;import android.support.v7.app.appcompatactivity;import android.os.bundle;import android.util.log;import android.view.layoutinflater;import android.view.view;import android.view.viewgroup;import android.widget.baseadapter;import android.widget.button;import android.widget.listview;import android.widget.progressbar;import com.example.a_0102.mylearn.r;import java.util.arraylist;import java.util.list;/** * 断点续传 * 一个文件可以分成几部分,使用不同的线程进行下载,使用数据库存储每个线程的下载进度 */public class downloadactivity extends appcompatactivity { private listview mlistview; private list<fileinfo> fileinfolist; private listviewadapter adapter; private updateuireceiver mupdateuireceiver; private downloadtaskimpl downloadtask; private button mbtndel; private intent intent; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_down_load); //申请权限 if (contextcompat.checkselfpermission(downloadactivity.this, manifest.permission.write_external_storage) != packagemanager.permission_granted) { //没有权限 log.e("------------->", "没有权限"); activitycompat.requestpermissions(downloadactivity.this, new string[]{manifest.permission.write_external_storage}, 0); } else { log.e("------------->", "已经有权限"); } mbtndel = findviewbyid(r.id.btn_del); downloadtask = new downloadtaskimpl(this); //从数据库获取要下载的文件 fileinfolist = new arraylist<>(); fileinfolist = downloadtask.getfileinfo(); //这里是用来模拟,具体请按照需求来写 if (fileinfolist.size() == 0) { fileinfo fileinfo1 = new fileinfo(0, "http://oslw24znh.bkt.clouddn.com/android2017_07_05.apk", "xiaobang.apk", 0, 0, 0); fileinfo fileinfo2 = new fileinfo(1, "http://ofmudsqae.bkt.clouddn.com/%e5%91%a8%e5%86%ac%e9%9b%a8%20-%20%e4%b8%8d%e5%ae%8c%e7%be%8e%e5%a5%b3%e5%ad%a9.mp3", "buwanmei.mp3", 0, 0, 0); fileinfolist.add(fileinfo1); fileinfolist.add(fileinfo2); } mlistview = findviewbyid(r.id.listview); adapter = new listviewadapter(); mlistview.setadapter(adapter); //为了测试写的,可忽略 mbtndel.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { log.e("------------>","dddsize:"+downloadtask.getfileinfo().size()); downloadtask.deletefileinfo(); log.e("------------>","size:"+downloadtask.getfileinfo().size()); downloadtask.deletethreadinfo(); } }); } //申请权限的回调 @override public void onrequestpermissionsresult(int requestcode, @nonnull string[] permissions, @nonnull int[] grantresults) { super.onrequestpermissionsresult(requestcode, permissions, grantresults); log.e("------------->", "requestcode:" + requestcode + "," + permissions[0]); if (requestcode == 0) { if (grantresults.length > 0 && grantresults[0] == packagemanager.permission_granted){ log.e("------------->", "授权被允许" ); }else { log.e("------------->", "授权没有被允许" ); } } } @override protected void onresume() { super.onresume(); // 1. 实例化broadcastreceiver子类 & intentfilter mupdateuireceiver = new updateuireceiver(); intentfilter intentfilter = new intentfilter(); // 2. 设置接收广播的类型 intentfilter.addaction("update_progressbar"); // 3. 动态注册:调用context的registerreceiver()方法 registerreceiver(mupdateuireceiver, intentfilter); } // 注册广播后,要在相应位置记得销毁广播// 即在onpause() 中unregisterreceiver(mbroadcastreceiver)// 当此activity实例化时,会动态将mybroadcastreceiver注册到系统中// 当此activity销毁时,动态注册的mybroadcastreceiver将不再接收到相应的广播 。 @override protected void onpause() { super.onpause(); //销毁在onresume()方法中的广播 unregisterreceiver(mupdateuireceiver); } @override protected void ondestroy() { super.ondestroy(); if (intent == null) { return; } stopservice(intent); } private class listviewadapter extends baseadapter { @override public int getcount() { return fileinfolist.size(); } @override public object getitem(int position) { return fileinfolist.get(position); } @override public long getitemid(int position) { return position; } @override public view getview(final int position, view convertview, viewgroup parent) { viewholder viewholder = null; if (convertview == null) { convertview = layoutinflater.from(downloadactivity.this).inflate(r.layout.layout_down_item, parent, false); viewholder = new viewholder(); viewholder.mprogress = convertview.findviewbyid(r.id.progress); viewholder.mbtndown = convertview.findviewbyid(r.id.btn_down); viewholder.mbtnstop = convertview.findviewbyid(r.id.btn_stop); convertview.settag(viewholder); //不用更新的尽量写在这里,防止每次都调用,进度设置为100 viewholder.mprogress.setmax(100); viewholder.mbtndown.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent = new intent(downloadactivity.this, downloadservice.class); intent.putextra("status", downloadservice.status_start); intent.putextra("fileinfo", fileinfolist.get(position)); startservice(intent); if (!downloadtask.isexitfileinfo(fileinfolist.get(position).getid())) { downloadtask.insertfileinfo(fileinfolist.get(position)); } } }); viewholder.mbtnstop.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent = new intent(downloadactivity.this, downloadservice.class); intent.putextra("status", downloadservice.status_stop); intent.putextra("fileinfo", fileinfolist.get(position)); startservice(intent); } }); } else { viewholder = (viewholder) convertview.gettag(); } fileinfo fileinfo = fileinfolist.get(position); viewholder.mprogress.setprogress(fileinfo.getprogress()); return convertview; } class viewholder { private progressbar mprogress; private button mbtndown; private button mbtnstop; } } /** * 用于更新ui的广播 * 使用静态注册的广播,广播的类如果是内部类,那么,该类必须为static修饰的类,否则has no zero argument constructor 这个异常 * https://blog.csdn.net/zhongjianblackberry/article/details/56670084 * 或者用动态注册广播 */ public class updateuireceiver extends broadcastreceiver { @override public void onreceive(context context, intent intent) { if (intent.getaction().equals("update_progressbar")) { int id = intent.getintextra("id", 0); int finished = intent.getintextra("finished", 0); int length = intent.getintextra("length", 0); if (length == 0 || length < 0) { return; } int progress = finished * 100 / length; fileinfo fileinfo = fileinfolist.get(id); fileinfo.setfinished(finished); fileinfo.setlength(length); fileinfo.setprogress(progress); adapter.notifydatasetchanged(); downloadtask.updatefileinfo(fileinfo, id); } } }}4、接下来是文件类和线程类的代码
public class fileinfo implements serializable { private int id; private string url;//文件的url private string file_name;//文件名称 private int progress;//当前进度(显示在进度条上的) private int finished;//已下载完的(实际下载的大小) private int length;//文件的大小 public fileinfo() { } public fileinfo(int id, string url, string file_name, int progress, int finished, int length) { this.id = id; this.url = url; this.file_name = file_name; this.progress = progress; this.finished = finished; this.length = length; } public int getid() { return id; } public void setid(int id) { this.id = id; } public string geturl() { return url; } public void seturl(string url) { this.url = url; } public string getfile_name() { return file_name; } public void setfile_name(string file_name) { this.file_name = file_name; } public int getprogress() { return progress; } public void setprogress(int progress) { this.progress = progress; } public int getlength() { return length; } public void setlength(int length) { this.length = length; } public int getfinished() { return finished; } public void setfinished(int finished) { this.finished = finished; } @override public string tostring() { return "fileinfo{" + "id=" + id + ", url='" + url + '\'' + ", file_name='" + file_name + '\'' + ", progress=" + progress + ", finished=" + finished + ", length=" + length + '}'; }}public class threadinfo implements serializable { private int id;//主键自增 private int thread_id;//如果没有id,唯一的标识,多线程的时候就不知道更新哪个了 private string url; private long start_flag; private long end_flag; private long finished;//该线程的下载进度 public threadinfo() { } public threadinfo(int thread_id, string url, long start_flag, long end_flag, long finished) { this.thread_id = thread_id; this.url = url; this.start_flag = start_flag; this.end_flag = end_flag; this.finished = finished; } public int getid() { return id; } public void setid(int id) { this.id = id; } public int getthread_id() { return thread_id; } public void setthread_id(int thread_id) { this.thread_id = thread_id; } public string geturl() { return url; } public void seturl(string url) { this.url = url; } public long getstart_flag() { return start_flag; } public void setstart_flag(long start_flag) { this.start_flag = start_flag; } public long getend_flag() { return end_flag; } public void setend_flag(long end_flag) { this.end_flag = end_flag; } public long getfinished() { return finished; } public void setfinished(long finished) { this.finished = finished; } @override public string tostring() { return "threadinfo{" + "id=" + id + ", thread_id=" + thread_id + ", url='" + url + '\'' + ", start_flag=" + start_flag + ", end_flag=" + end_flag + ", finished=" + finished + '}'; }}5、数据库的代码
这里要用单例模式,否则会报错
import android.content.context;import android.database.sqlite.sqlitedatabase;import android.database.sqlite.sqliteopenhelper;/** * 要用单例的,否则会出现cannot perform this operation because the connection pool has been closed */public class dbhalper extends sqliteopenhelper { private static final string db_name = "downloadfile"; private static final int db_version = 1; private static final string create_thread_info = "create table thread_info (id integer primary key autoincrement,thread_id int,url text ,start_flag int,end_flag int,finished int);"; private static final string create_file_info = "create table file_info (id integer primary key,url text ,file_name text,length int,progress int,finished int);"; private static dbhalper dbhalper; public static dbhalper getdbhalper(context context){ if(dbhalper == null){ dbhalper = new dbhalper(context); } return dbhalper; } private dbhalper(context context) { super(context, db_name, null, db_version); } @override public void oncreate(sqlitedatabase db) { db.execsql(create_thread_info); db.execsql(create_file_info); } @override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { }}public interface idownloadtask { /** * 插入线程信息 * * @param threadinfo */ void insertthreadinfo(threadinfo threadinfo); /** * 更新线程信息 * * @param threadinfo * @param id */ void updatethreadinfo(threadinfo threadinfo, int id, string url); /** * 删除下载完成的线程记录 * * @param url */ void deletethreadinfo(string url); /** * 获取所有线程信息 * * @param url * @return */ list<threadinfo> getthreadinfos(string url); /** * 获取所有线程信息 * * @return */ list<threadinfo> getthreadinfos(); /** * 插入文件信息 * * @param fileinfo */ void insertfileinfo(fileinfo fileinfo); /** * 修改文件的信息 * * @param fileinfo * @param id */ void updatefileinfo(fileinfo fileinfo, int id); /** * 该文件信息是否存在 * * @param id * @return */ boolean isexitfileinfo(int id); /** * 查询文件信息 * * @return */ list<fileinfo> getfileinfo(); /** * 删除文件信息 */ void deletefileinfo(); /** * 删除文件下载的线程信息 */ void deletethreadinfo();}接口类的实现,注意同步,否则多个线程一起操作一个方法会出现“惊喜“
【Android实现多线程断点续传】import android.content.context;import android.database.cursor;import android.database.sqlite.sqlitedatabase;import java.util.arraylist;import java.util.list;/** * 增、删、改方法要保证线程安全,同一时刻只能有一个线程访问 */public class downloadtaskimpl implements idownloadtask { private dbhalper dbhalper; private sqlitedatabase db; public downloadtaskimpl(context context) { dbhalper = dbhalper.getdbhalper(context); } @override public synchronized void insertthreadinfo(threadinfo threadinfo) { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("insert into thread_info (thread_id,url,start_flag,end_flag,finished) values (?,?,?,?,?);", new object[]{threadinfo.getthread_id(),threadinfo.geturl(),threadinfo.getstart_flag(), threadinfo.getend_flag(),threadinfo.getfinished()}); db.close(); } @override public synchronized void updatethreadinfo(threadinfo threadinfo, int thread_id,string url) { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("update thread_info set thread_id=?, url=?,start_flag=?,end_flag=?,finished=? where thread_id = ? and url = ?;", new object[]{threadinfo.getthread_id(),threadinfo.geturl(), threadinfo.getstart_flag(), threadinfo.getend_flag(),threadinfo.getfinished(),thread_id,url}); db.close(); } @override public synchronized void deletethreadinfo(string url) { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("delete from thread_info where url=?;",new string[]{url}); db.close(); } @override public list<threadinfo> getthreadinfos(string url) { list<threadinfo> threadinfos = new arraylist<>(); sqlitedatabase db = dbhalper.getreadabledatabase(); cursor cursor = db.rawquery("select * from thread_info where url=?;",new string[]{url}); while (cursor.movetonext()){ threadinfo threadinfo = new threadinfo(); threadinfo.setthread_id(cursor.getint(cursor.getcolumnindex("thread_id"))); threadinfo.seturl(cursor.getstring(cursor.getcolumnindex("url"))); threadinfo.setstart_flag(cursor.getint(cursor.getcolumnindex("start_flag"))); threadinfo.setend_flag(cursor.getint(cursor.getcolumnindex("end_flag"))); threadinfo.setfinished(cursor.getint(cursor.getcolumnindex("finished"))); threadinfos.add(threadinfo); } cursor.close(); db.close(); return threadinfos; } @override public list<threadinfo> getthreadinfos() { list<threadinfo> threadinfos = new arraylist<>(); sqlitedatabase db = dbhalper.getreadabledatabase(); cursor cursor = db.rawquery("select * from thread_info;",new string[]{}); while (cursor.movetonext()){ threadinfo threadinfo = new threadinfo(); threadinfo.setthread_id(cursor.getint(cursor.getcolumnindex("thread_id"))); threadinfo.seturl(cursor.getstring(cursor.getcolumnindex("url"))); threadinfo.setstart_flag(cursor.getint(cursor.getcolumnindex("start_flag"))); threadinfo.setend_flag(cursor.getint(cursor.getcolumnindex("end_flag"))); threadinfo.setfinished(cursor.getint(cursor.getcolumnindex("finished"))); threadinfos.add(threadinfo); } cursor.close(); db.close(); return threadinfos; } @override public synchronized void insertfileinfo(fileinfo fileinfo) { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("replace into file_info (id,url,file_name,length,progress,finished) values (?,?,?,?,?,?);", new object[]{fileinfo.getid(),fileinfo.geturl(),fileinfo.getfile_name(),fileinfo.getlength(), fileinfo.getprogress(),fileinfo.getfinished()}); db.close(); } @override public synchronized void updatefileinfo(fileinfo fileinfo, int id) { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("update file_info set id=?, url=?,file_name=?,length=?,progress=?,finished=? where id = ?;", new object[]{fileinfo.getid(),fileinfo.geturl(), fileinfo.getfile_name(),fileinfo.getlength(), fileinfo.getprogress(),fileinfo.getfinished(),id}); db.close(); } @override public boolean isexitfileinfo(int id) { sqlitedatabase db = dbhalper.getreadabledatabase(); boolean isexit = false; cursor cursor = db.rawquery("select * from file_info where id=?;",new string[]{id+""}); while (cursor.movetonext()){ isexit = true; } cursor.close(); db.close(); return isexit; } @override public list<fileinfo> getfileinfo() { list<fileinfo> fileinfos = new arraylist<>(); sqlitedatabase db = dbhalper.getreadabledatabase(); cursor cursor = db.rawquery("select * from file_info;",new string[]{}); while (cursor.movetonext()){ fileinfo fileinfo = new fileinfo(); fileinfo.setid(cursor.getint(cursor.getcolumnindex("id"))); fileinfo.seturl(cursor.getstring(cursor.getcolumnindex("url"))); fileinfo.setfile_name(cursor.getstring(cursor.getcolumnindex("file_name"))); fileinfo.setlength(cursor.getint(cursor.getcolumnindex("length"))); fileinfo.setprogress(cursor.getint(cursor.getcolumnindex("progress"))); fileinfo.setfinished(cursor.getint(cursor.getcolumnindex("finished"))); fileinfos.add(fileinfo); } cursor.close(); db.close(); return fileinfos; } @override public synchronized void deletefileinfo() { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("delete from file_info;",new string[]{}); db.close(); } @override public void deletethreadinfo() { sqlitedatabase db = dbhalper.getwritabledatabase(); db.execsql("delete from thread_info;",new string[]{}); db.close(); }}提示:可以直接使用filedownloader一个开源的下载大文件的框架,使用就自行百度吧
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com 。
-- 展开阅读全文 --
推荐阅读
- 蜂蛹怎么吃最有营养,蜂子幼崽怎么吃营养最佳
- Android实现多张图片合成加载动画
- 古诗春风的意思
- wifi6跟wifi5的区别
- 重庆为什么简称渝 重庆市简称渝的由来
- 3月这4大星座旧爱来袭,再续前缘,重燃爱火
- 这些星座在一起时间越长,彼此越深爱,感情只增不减
- 古代胭脂是指什么
- 异性缘超级好,对待感情却能够从一而终的三大星座,遇到就别错过