当前位置:首页 > 谈天说地 > 正文内容

Android实现多线程断点续传

34资源网2022年07月28日 11:01238

本文实例为大家分享了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一个开源的下载大文件的框架,使用就自行百度吧

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。

看完文章,还可以用支付宝扫描下面的二维码领取一个支付宝红包,目前可领1-88元不等

支付宝红包二维码

除了扫码可以领取之外,大家还可以(复制 720087999 打开✔支付宝✔去搜索, h`o`n.g.包哪里来,动动手指就能领)。

看下图所示是好多参与这次活动领取红包的朋友:

支付宝红包

扫描二维码推送至手机访问。

版权声明:本文由34楼发布,如需转载请注明出处。

本文链接:https://www.34l.com/post/19944.html

分享给朋友:

相关文章

用一个仍然造句和用三个仍然造句
用一个仍然造句和用三个仍然造句

用一个仍然造句:老张生病了,但他仍然坚守在工作岗位上。虽然他学习英语三年了,但他仍然不能流利的使用英语对话。当今社会仍然有很多贫困地区的孩子上不起学校。这么多年没有见到老朋友,他的样貌仍然美丽动人。用三个仍然造句:虽然小明的学习成绩一直不好...

打败你的不一定是你的对手,有可能是一个过路人
打败你的不一定是你的对手,有可能是一个过路人

有句话叫做“羊毛出在狗身上,由猪买单”现阶段打败你的不一定是对手而是一个过路人。最近,尼康退出中国,裁员两千人!很多人以为尼康是被同行打败,没想到居然是毫无相关的行业。尼康直接宣布破产的真相:受智能手机普及的影响!有一部很牛的科幻小说,名字...

互联网公司好日子到头,逻辑彻底变了
互联网公司好日子到头,逻辑彻底变了

好日子到头了,逻辑彻底变了,互联网公司已经不再是香饽饽。有两个重要的信号。一是资本不能无序扩张;二是互联网平台税率上调;前者直接宣布现在的那些玩家,你们继续玩,这没关系。但是想要通过资本野蛮扩大,不公平竞争,这就甭想了。后者直接影响到了互联...

抖音传话筒项目(傻瓜式复制粘贴轻松月入3000+)
抖音传话筒项目(傻瓜式复制粘贴轻松月入3000+)

可能你觉得你写不出优秀的文案,可能你觉得你没办法配音,可能你觉得不好意思露脸,但又想通过抖音来赚钱,那么今天给大家来说说这个抖音传话筒项目,只需要复制粘贴,一个月轻松赚到3000+,无需露脸配音,更加不需要写文案。上图是我通过抖音搜索“传话...

虚拟内存太低怎么设置(电脑磁盘空间不足清理步骤)
虚拟内存太低怎么设置(电脑磁盘空间不足清理步骤)

在电脑的平时使用中,经常会出现内存不足的提示,有时可能小伙伴们会疑惑了,明明自己是16G内存的性能为何也能出现这种提示呢?这是当你在运行多个大程序的时候,对内存的需求非常大,当物理内存不能满足需求时,有可能导致程序关闭而数据保存错误。那么在...

创业前4年无产品,量产一年销售近亿元,这家公司怎么做到的?
创业前4年无产品,量产一年销售近亿元,这家公司怎么做到的?

光子晶体前4年都在死磕产品研发,直到去年才正式量产,目前已实现每月数万平米的光学显示膜出货,销售额近亿元,收获了苹果、亚马逊等合作伙伴,在透明显示领域开了先河。 作者丨解夏 编辑丨及轶嵘 图源丨受访者 “家里的窗户、汽车车窗、公司的玻璃...