多线程下载和断点续传

@Override
public void success(getDataBean getDataBean) {
        Double  version = Double.parseDouble(getVersion());
        path = getDataBean.getData().getApkUrl();
        Double versionName = Double.valueOf(getDataBean.getData().getVersionName());
        if (version<versionName){
        Toast.makeText(gexinActivity.this,"更新",Toast.LENGTH_SHORT).show();
        showdialog();
        }else{
        Toast.makeText(gexinActivity.this,"不更新",Toast.LENGTH_SHORT).show();
        }
        }
private void showdialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = getLayoutInflater();
final View layout = inflater.inflate(R.layout.dialog_customize, null);
        Button btn_start = layout.findViewById(R.id.btn_start);
        Button btn_quxiao = layout.findViewById(R.id.btn_quxiao);
        //开始下载
        btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
        dlg.dismiss();
        dowloddialog();
        }
        });
        btn_quxiao.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
        dlg.dismiss();
        finish();
        }
        });
        builder.setView(layout);
        dlg = builder.create();
        dlg.show();
        }

private void dowloddialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = getLayoutInflater();
final View layout = inflater.inflate(R.layout.dialog_dowload, null);
        pb = layout.findViewById(R.id.pb);
        jindu = layout.findViewById(R.id.jindu);
        builder.setView(layout);
        dialogs = builder.create();
        dialogs.show();
        //开始下载
        download();
        }

private void download() {
        Thread t = new Thread() {
//执行子线程(下载文件)
@Override
public void run() {
        try {
        //将下载地址封装成URL对象
        URL url = new URL(path);
        //创建连接对象,此时未建立连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求方式为get请求
        conn.setRequestMethod("GET");
        //设置连接超时
        conn.setConnectTimeout(5000);
        //设置读取超时
        conn.setReadTimeout(5000);
        //如果请求成功
        if(conn.getResponseCode() == 200) {
        //获得需要下载的文件的长度
        int length = conn.getContentLength();
        //设置进度条的最大值就是原文件的总长度
        pb.setMax(length);
        //创建File对象
        File file = new File(Environment.getExternalStorageDirectory(), fileName);
        //创建临时文件
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");
        //设置临时文件的大小
        raf.setLength(length);
        //关闭临时文件
        raf.close();
        //计算出每个线程应该下载多少字节
        int size = length / ThreadCount;
        //遍历下载线程
        for (int i = 0; i < ThreadCount; i++) {
        //计算线程下载的开始位置
        int startIndex = i * size;
        //计算线程下载的结束位置
        int endIndex = (i + 1) * size - 1;
        //如果是最后一个线程,那么结束位置写死
        if(i == ThreadCount - 1) {
        endIndex = length - 1;
        }

        //创建下载线程
        DownLoadThread thread = new DownLoadThread(startIndex, endIndex, i);

        //启动下载线程
        thread.start();
        }
        }
        } catch (Exception e) {

        e.printStackTrace();
        }
        }
        };
        t.start();
        }
class DownLoadThread extends Thread {

    //下载开始的位置
    int startIndex;

    //下载结束的位置
    int endIndex;

    //下载线程的id
    int threadId;

    //下载线程类的构造方法
    public DownLoadThread(int startIndex, int endIndex, int threadId) {
        super();
        this.startIndex = startIndex;
        this.endIndex = endIndex;
        this.threadId = threadId;
    }

    //执行下载线程
    @Override
    public void run() {

        try {

            //创建进度临时文件
            File progressFile = new File(Environment.getExternalStorageDirectory(), threadId + ".txt");

            //如果SD卡中存在进度临时文件
            if(progressFile.exists()) {

                //创建文件输出流
                FileInputStream fis = new FileInputStream(progressFile);

                //InputStreamReader:创建输输入流缓冲区
                //BufferedReader:创建读取缓冲区
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                //从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置
                int lastProgress = Integer.parseInt(br.readLine());

                //设置初始位置
                startIndex += lastProgress;

                //把上次下载的进度显示至进度条
                currentProgress += lastProgress;
                pb.setProgress(currentProgress);

                //发送消息,让主线程刷新文本进度
                handler.sendEmptyMessage(1);

                //关闭文件输入流
                fis.close();
            }

            System.out.println("线程" + threadId + "的下载区间是:" + startIndex + "---" + endIndex);

            //将下载地址封装成URL对象
            URL url = new URL(path);

            //创建连接对象,此时未建立连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            //设置请求方式为get请求
            conn.setRequestMethod("GET");

            //设置连接超时
            conn.setConnectTimeout(5000);

            //设置读取超时
            conn.setReadTimeout(5000);

            //设置本次http请求所请求的数据的区间
            conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

            //请求部分数据,相应码是206
            if(conn.getResponseCode() == 206) {

                //流里此时只有1/3原文件的数据
                InputStream is = conn.getInputStream();

                byte[] b = new byte[1024];
                int len = 0;
                int total = 0;

                //拿到临时文件的输出流
                File file = new File(Environment.getExternalStorageDirectory(), fileName);

                //使用临时文件输出流创建临时文件
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");

                //把文件的写入位置移动至startIndex
                raf.seek(startIndex);

                while((len = is.read(b)) != -1) {

                    //每次读取流里数据之后,同步把数据写入临时文件
                    raf.write(b, 0, len);
                    total += len;

                    System.out.println("线程" + threadId + "下载了" + total);

                    //每次读取流里数据之后,把本次读取的数据的长度显示至进度条
                    currentProgress += len;
                    pb.setProgress(currentProgress);

                    //发送消息,让主线程刷新文本进度
                    handler.sendEmptyMessage(1);

                    //生成一个专门用来记录下载进度的临时文件
                    RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");

                    //每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中
                    progressRaf.write((total + "").getBytes());

                    //关闭临时文件
                    progressRaf.close();
                }

                System.out.println("线程" + threadId + "下载完毕-------------------小志参上!");

                //关闭临时文件
                raf.close();

                //下载结束的进程个数加1
                finishedThread++;

                synchronized (path) {

                    //如果所有的下载进程都下载结束
                    if(finishedThread == ThreadCount) {

                        //遍历下载进度
                        for (int i = 0; i < ThreadCount; i++) {

                            //获取下载进度所在的文件
                            File f = new File(Environment.getExternalStorageDirectory(), i + ".txt");

                            //删除保存下载进度的临时文件
                            f.delete();
                        }

                        //下载结束的下载线程的个数设置为0
                        finishedThread = 0;
                    }
                }
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}
    
    public String getVersion() {
        try {
            PackageManager manager = this.getPackageManager();
            PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
            String version = info.versionName;
            return " " + version;
        } catch (Exception e) {
            e.printStackTrace();
            return "gun";
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值