Android实现多线程断点续传
本文实例为大家分享了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();
}接口类的实现,注意同步,否则多个线程一起操作一个方法会出现“惊喜“
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一个开源的下载大文件的框架,使用就自行百度吧
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。
看完文章,还可以扫描下面的二维码下载快手极速版领4元红包
除了扫码领红包之外,大家还可以在快手极速版做签到,看视频,做任务,参与抽奖,邀请好友赚钱)。
邀请两个好友奖最高196元,如下图所示:







