多线程下载断点续传

package com.itheima.multithreaddownload;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {

    String path = "http://169.254.244.136:8080/QQPlayer.exe";
    int threadCount = 3;
    int finishedThread = 0;
    //所有线程下载总进度
    int downloadProgress = 0;
    private ProgressBar pb;
    private TextView tv;

    Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            tv.setText((long)pb.getProgress() * 100 / pb.getMax() + "%");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pb = (ProgressBar) findViewById(R.id.pb);
        tv = (TextView) findViewById(R.id.tv);
    }


    public void click(View v){
        Thread t = new Thread(){
            @Override
            public void run() {
                //发送http请求,拿到目标文件长度
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(8000);
                    conn.setReadTimeout(8000);

                    if(conn.getResponseCode() == 200){
                        //获取长度
                        int length = conn.getContentLength();

                        //创建临时文件
                        File file = new File(Environment.getExternalStorageDirectory(), getNameFromPath(path));
                        RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                        //设置临时文件大小与目标文件一致
                        raf.setLength(length);
                        raf.close();

                        //设置进度条的最大值
                        pb.setMax(length);

                        //计算每个线程下载区间
                        int size = length / threadCount;

                        for (int id = 0; id < threadCount; id++) {
                            //计算每个线程下载的开始位置和结束位置
                            int startIndex = id * size;
                            int endIndex = (id + 1) * size - 1;
                            if(id == threadCount - 1){
                                endIndex = length - 1;
                            }
                            System.out.println("线程" + id + "下载的区间:" + startIndex + " ~ " + endIndex);
                            new DownLoadThread(id, startIndex, endIndex).start();
                        }

                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        };
        t.start();
    }

    public String getNameFromPath(String path){
        int index = path.lastIndexOf("/");
        return path.substring(index + 1);
    }

    class DownLoadThread extends Thread{

        int threadId;
        int startIndex;
        int endIndex;


        public DownLoadThread(int threadId, int startIndex, int endIndex) {
            super();
            this.threadId = threadId;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
        }


        @Override
        public void run() {
            try {
                File fileProgress = new File(Environment.getExternalStorageDirectory(), threadId + ".txt");
                int lastProgress = 0;
                if(fileProgress.exists()){
                    //读取进度临时文件中的内容
                    FileInputStream fis = new FileInputStream(fileProgress);
                    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                    //得到上一次下载进度
                    lastProgress = Integer.parseInt(br.readLine());
                    //改变下载的开始位置,上一次下过的,这次就不请求了
                    startIndex += lastProgress;
                    fis.close();

                    //把上一次下载进度加到进度条进度中
                    downloadProgress += lastProgress;
                    pb.setProgress(downloadProgress);

                    //发送消息,让文本进度条改变
                    handler.sendEmptyMessage(1);
                }

                //发送http请求,请求要下载的数据
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(8000);
                conn.setReadTimeout(8000);
                //设置请求数据的区间
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

                //请求部分数据,成功的响应码是206
                if(conn.getResponseCode() == 206){
                    InputStream is = conn.getInputStream();

                    byte[] b = new byte[1024];
                    int len = 0;
                    //当前线程下载的总进度
                    int total = lastProgress;
                    File file = new File(Environment.getExternalStorageDirectory(), getNameFromPath(path));
                    RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                    //设置写入的开始位置
                    raf.seek(startIndex);
                    while((len = is.read(b)) != -1){
                        raf.write(b, 0, len);
                        total += len;
                        System.out.println("线程" + threadId + "下载了:" + total);


                        //创建一个进度临时文件,保存下载进度
                        RandomAccessFile rafProgress = new RandomAccessFile(fileProgress, "rwd");
                        //每次下载1024个字节,就,就马上把1024写入进度临时文件
                        rafProgress.write((total + "").getBytes());
                        rafProgress.close();

                        //每次下载len个长度的字节,马上把len加到下载进度中,让进度条能反应这len个长度的下载进度
                        downloadProgress += len;
                        pb.setProgress(downloadProgress);

                        //发送消息,让文本进度条改变
                        handler.sendEmptyMessage(1);

                    }
                    raf.close();
                    System.out.println("线程" + threadId + "下载完毕------------------");

                    //3条线程全部下载完毕,才去删除进度临时文件
                    finishedThread++;

                    synchronized (path) {
                        if(finishedThread == threadCount){
                            for (int i = 0; i < threadCount; i++) {
                                File f = new File(Environment.getExternalStorageDirectory(), i + ".txt");
                                f.delete();
                            }
                            finishedThread = 0;
                        }
                    }
                }

            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
<?xml version="1.0"?>

-<LinearLayout android:orientation="vertical" tools:context=".MainActivity" android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">

<Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:onClick="click" android:text="下载"/>

<ProgressBar android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/pb" style="@android:style/Widget.ProgressBar.Horizontal"/>

<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="0%" android:id="@+id/tv" android:layout_gravity="right"/>

</LinearLayout>
<?xml version="1.0" encoding="UTF-8"?>

-<manifest android:versionName="1.0" android:versionCode="1" package="com.itheima.multithreaddownload" xmlns:android="http://schemas.android.com/apk/res/android">

<uses-sdk android:targetSdkVersion="17" android:minSdkVersion="8"/>

<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


-<application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:allowBackup="true">


-<activity android:name="com.itheima.multithreaddownload.MainActivity" android:label="@string/app_name">


-<intent-filter>

<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

</application>

</manifest>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值