多线程断线下载

执行下载的主程序MainActivity

public class DemoActivity extends Activity implements OnClickListener {

    private ProgressBar pb;
    private Button bt;
    private TextView tv;
    private EditText et;
    boolean flag = true;
    boolean stopflag = false;
    private Handler handler = new Handler() {
//进度条下面是-- 当前下载大小/总大小            下载速度
        @Override
        public void handleMessage(Message msg) {
            pb.setProgress(total);

            int max = pb.getMax();    //获取进度条的上限值
            if (total >= (max - 1)) {
                total = max;
                flag = false;
            }
            int result = (total * 100 / max);
            tv.setText("当前进度 :" + result + "%");

            super.handleMessage(msg);
        }
    };

    int total = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        pb = (ProgressBar) this.findViewById(R.id.pb);
        bt = (Button) this.findViewById(R.id.bt);
        tv = (TextView) this.findViewById(R.id.tv_process);
        et = (EditText) this.findViewById(R.id.et);
        bt.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt:
            // 创建一个子线程 定期的更新ui
            if ("开始下载".equals(bt.getText().toString())) {
                //原来是"开始下载" 按下去 变成"暂停" 程序暂停下载 下载标志为false
                bt.setText("暂停");
                stopflag = false; // 开始下载
            } else {
                bt.setText("开始下载");
                stopflag = true;
            }
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    while (flag) {
                        try {
                            //每暂停一秒 更新一下下载百分数
                            sleep(1000);
                            // 如果total > = 文件长度
                            Message msg = new Message();
                            handler.sendMessage(msg);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }.start();

            // 开始执行下载的操作
            String path = et.getText().toString().trim();
            if ("".equals(path)) {
                Toast.makeText(this, "路径不能为空", 1).show();
                return;
            }
            try {
                //连接服务器 -- 获取服务器上面资源总大小,并设置进度条,启动下载
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                //设置支持的浏览器
                conn.setRequestProperty("User-Agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                int code = conn.getResponseCode();
                if (code == 200) {
                    int len = conn.getContentLength();
                    RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/"
                            + getFilenName(path), "rwd");
                    // 1.设置本地文件大小跟服务器的文件大小一致
                    file.setLength(len);
                    // 设置进度条的最大值
                    pb.setMax(len);

                    // 2 .假设开启3 个线程
                    int threadnumber = 3;
                    int blocksize = len / threadnumber;
                    /**
                     * 线程1 0~ blocksize 线程2 1*bolocksize ~ 2*blocksize 线程3
                     * 2*blocksize ~ 文件末尾
                     */
                    for (int i = 0; i < threadnumber; i++) {
                        int startposition = i * blocksize;
                        int endpositon = (i + 1) * blocksize;
                        if (i == (threadnumber - 1)) {
                            // 最后一个线程
                            endpositon = len;
                        }

                        DownLoadTask task = new DownLoadTask(i, path,
                                startposition, endpositon);
                        task.start();
                    }

                }
            } catch (Exception e) {
                Toast.makeText(this, "下载出现异常", 0).show();
                e.printStackTrace();
            }

            break;
        }

    }

    class DownLoadTask extends Thread {

        int threadid;
        String filepath;
        int startposition;
        int endpositon;

        public DownLoadTask(int threadid, String filepath, int startposition,
                int endpositon) {
            this.threadid = threadid;
            this.filepath = filepath;
            this.startposition = startposition;
            this.endpositon = endpositon;

        }

        @Override
        public void run() {
            try {
                //记录当前已经下载的文件
                File postionfile = new File("/mnt/sdcard/" + threadid + ".txt");
                URL url = new URL(filepath);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                System.out.println("线程" + threadid + "正在下载 " + "开始位置 : "
                        + startposition + "结束位置 " + endpositon);

                if (postionfile.exists()) {
                    FileInputStream fis = new FileInputStream(postionfile);
                    //此数组表示已经从服务器下载的数据量
                    byte[] result = StreamTool.getBytes(fis);
                    String str = new String(result);
                    //设置新的下载位置
                    if (!"".equals(str)) {
                        int newstartposition = Integer.parseInt(str);
                        if (newstartposition > startposition) {
                            startposition = newstartposition;
                        }
                    }
                }

                // "Range", "bytes=2097152-4194303")
                conn.setRequestProperty("Range", "bytes=" + startposition + "-"
                        + endpositon);
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                conn.setRequestProperty("User-Agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                InputStream is = conn.getInputStream();
                //执行随机读写
                RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/"
                        + getFilenName(filepath), "rwd");
                // 设置 数据从文件哪个位置开始写
                file.seek(startposition);
                byte[] buffer = new byte[1024];
                int len = 0;
                // 代表当前读到的服务器数据的位置 ,同时这个值已经存储的文件的位置
                int currentPostion = startposition;
                // 创建一个文件对象 ,记录当前某个文件的下载位置

                while ((len = is.read(buffer)) != -1) {
                    if (stopflag) {
                        return;
                    }
                    file.write(buffer, 0, len);

                    synchronized (DemoActivity.this) {
                        total += len;
                    }

                    currentPostion += len;
                    // 需要把currentPostion 信息给持久化到存储设备
                    String position = currentPostion + "";
                    FileOutputStream fos = new FileOutputStream(postionfile);
                    fos.write(position.getBytes());
                    fos.flush();
                    fos.close();
                }

                file.close();
                System.out.println("线程" + threadid + "下载完毕");
                // 当线程下载完毕后 把文件删除掉
                if (postionfile.exists()) {
                    postionfile.delete();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            super.run();
        }

    }

    public String getFilenName(String path) {
        int start = path.lastIndexOf("/") + 1;
        return path.substring(start, path.length());
    }
}

使用到的工具类StreamTool

public class StreamTool {
    /**
     * 把一个inputstream里面的内容转化成一个byte[] 
     */
    
    public static byte[] getBytes(InputStream is) throws Exception{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = is.read(buffer))!=-1){
            bos.write(buffer, 0, len);
        }
        is.close();
        bos.flush();
        byte[] result = bos.toByteArray();
        System.out.println(new String(result));
        return  result;
    }
}


布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/down_load" />

    <EditText
        android:id="@+id/et"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="@string/hint"
        android:text="http://192.168.1.101:8080/youdao.exe" />

    <ProgressBar
        android:id="@+id/pb"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_process"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/bt"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/download" />

</LinearLayout>
原文地址:https://www.cnblogs.com/android-zcq/p/3388924.html