android开发分享Android实现多线程断点续传

本文实例为大家分享了android实现多线程断点续传的具体代码,供大家参考,具体内容如下多线程下载涉及到的知识点:1、service的使用:我们在service中去下载文件;2、thread的使用:s

android开发分享Android实现多线程断点续传实例为大家分享了android实现多线程断点续传的具体代码,供大家参考,具体内容如下

上述就是android开发分享Android实现多线程断点续传的全部内容,如果对大家有所用处且需要了解更多关于Android学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

多线程下载涉及到的知识点:

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, "https://oslw24znh.bkt.clouddn.com/android2017_07_05.apk", "xiaobang.apk", 0, 0, 0);              fileinfo fileinfo2 = new fileinfo(1, "https://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一个开源的下载大文件的框架,使用就自行百度吧

以上就是android开发分享Android实现多线程断点续传的全部内容,希望对大家的学习有所帮助,也希望大家多多支持<计算机技术网(www.ctvol.com)!!>。

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/1174657.html

(0)
上一篇 2022年8月3日
下一篇 2022年8月3日

精彩推荐