• 多线程断线下载


    执行下载的主程序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>
  • 相关阅读:
    C# 如何telnet IP的某端口/ping 是否通
    centos7.9设置系统时间,并同步到硬件
    基于阿里云 DNS API 实现的 DDNS 工具
    GridControl 通用类2
    使用JSON.stringify时需注意的坑
    java中BigDecimal和0比较
    c# WindowsCommunityToolkit--- Shade Animation
    WPF 取消在触屏上点击按下不松开会出现矩形背景的效果
    c# 反射私有类和私有方法
    c# 汉字转拼音
  • 原文地址:https://www.cnblogs.com/android-zcq/p/3388924.html
Copyright © 2020-2023  润新知