android多线程下载——--显示进度条,断点下载—--—(Demo)

一:在线程下载的同时显示进度条,如图效果显示 :(本次测试使用了三个线程进行下载,所以有三个显示进度条)


二.实现的代码如下:

1.布局代码:(我已经将下载的路径写死了,自己灵活变动一下)

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

    <EditText
        android:id="@+id/et_url"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="http://192.168.1.109/kugou.exe" />

    <Button
        android:id="@+id/bt_download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="download"
        android:text="download" />

    <ProgressBar
        android:id="@+id/pb_01"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp" />

    <ProgressBar
        android:id="@+id/pb_02"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp" />

    <ProgressBar
        android:id="@+id/pb_03"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp" />


</LinearLayout>

2.Activity的实现代码:

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

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;

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    EditText et_url;

    ProgressBar pb_01;
    ProgressBar pb_02;
    ProgressBar pb_03;

    // 设置线程的数量为3
    private final static int THRED_COUNT = 3;
    final static String path = "http://192.168.1.109/kugou.exe";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et_url = (EditText) findViewById(R.id.et_url);
        pb_01 = (ProgressBar) findViewById(R.id.pb_01);
        pb_02 = (ProgressBar) findViewById(R.id.pb_02);
        pb_03 = (ProgressBar) findViewById(R.id.pb_03);


    }

    //点击下载事件
    public void download(View view) {
        final String et_path = et_url.getText().toString().trim();
        if (TextUtils.isEmpty(et_path)) {
            Toast.makeText(this, "地址不能为空", Toast.LENGTH_SHORT).show();
            return;
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                // 创建三个线程进行多线程的下载资源文件
                try {
                    URL url = new URL(path);
                    // 1.获取文件资源的连接
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    // 2.获取服务器资源文件的大小
                    int length = conn.getContentLength();

                    //3.在本地生成与之一样的文件,使用随机流
                    RandomAccessFile raf = new RandomAccessFile(getFilename(), "rw");
                    //设置文件的长度
                    raf.setLength(length);

                    //4.开始划分每一个线程从什么位置下载到什么位置
                    int blockSize = length / THRED_COUNT;

                    //5.开启3个线程进行下载

                    for (int threadId = 0; threadId < THRED_COUNT; threadId++) {

                        //每个线程的下载开始位置
                        int startIndex = threadId * blockSize;

                        //线程下载的结束位置
                        int endIndex = (threadId + 1) * blockSize - 1;

                        //如果是最后一个线程,让这个线程执行后面剩余的文字资源
                        if (threadId == THRED_COUNT) {
                            endIndex = length - 1;
                        }

                        //开始线程去下载,并传递进去每一个线程下载的起始位置

                        new Downloader(threadId, startIndex, endIndex).start();
                    }

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

            }
        }).start();


    }

    class Downloader extends Thread {
        private int startIndex;
        private int endIndex;
        private int threadId;
        private int currentPosition;

        public Downloader(int threadId, int startIndex, int endIndex) {
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadId = threadId;
            currentPosition = startIndex;
            System.out.println("线程" + threadId + "-下载的位置从:" + startIndex + " ---" + endIndex);
        }

        @Override
        public void run() {
            try {
                //先找到之前记录好的位置信息
                File file = new File(getFiledir()+threadId + ".position");

                //判断以前曾经下载过文件,这个时候必须读取里里面的位置信息
                //(断点下载的方式:就是记录每次下载之后的位置,并实时保存到硬盘中,所以使用到了随机流进行实时写出断点下载的位置文件信息)
                if (file.exists() && file.length() > 0) {
                    FileInputStream fis = new FileInputStream(file);
                    BufferedReader bReader = new BufferedReader(new InputStreamReader(fis));
                    //读取线程曾经下载到的位置
                    currentPosition = Integer.parseInt(bReader.readLine());
                    System.out.println("以前有下载过文件--" + threadId + "--从" + currentPosition + "开始下载");
                    bReader.close();
                    fis.close();

                } else {
                    System.out.println("以前没有下载过文件,从头开始下载------");
                }

                URL url = new URL(path);

                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //conn.getInputStream()//获取这个资源对应的所有输入流
                //为了实现每一线程下载的东西都是固有的位置,所以必须告诉服务器,每一个线程从什么位置开始下载

                //设置线程下载资源的位置
                conn.setRequestProperty("Range", "bytes:" + currentPosition + "-" + endIndex);

                //获取线程访问返回的状态码    线程下载返回的是206
                int code = conn.getResponseCode();

                if (206 == code) {
                    InputStream in = conn.getInputStream();
                    //写文件的时候要注意,因为已经规定了每一个线程从什么位置开始下载,所以
                    //写数据的时候必须从指定位置开始写入
                    RandomAccessFile raf = new RandomAccessFile(getFilename(), "rw");
                    raf.seek(currentPosition);


                    byte[] buffer = new byte[1024];
                    int len = 0;
                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);

                        //这几必须写在上面这句语句后面,不然会数据混乱问题出现问题
                        currentPosition += len;

                        //必须使用随机流进行读写现在下载位置的配置信息,不然会出现各种问题,(主要是硬盘的缓存问题)
                        RandomAccessFile fos = new RandomAccessFile(getFiledir()+threadId + ".position", "rwd");
                        fos.write((currentPosition + "").getBytes());
                        fos.close();


                        //进度条显示
                        if(threadId == 0){
                            pb_01.setMax(endIndex-startIndex);
                            pb_01.setProgress(currentPosition-startIndex);
                        }else if(threadId == 1){
                            pb_02.setMax(endIndex-startIndex);
                            pb_02.setProgress(currentPosition-startIndex);
                        }else if(threadId == 2){
                            pb_03.setMax(endIndex-startIndex);
                            pb_03.setProgress(currentPosition-startIndex);
                        }
                    }
                    System.out.println("线程" + threadId + "--已经下载结束了。。");
                    //下载完成之后,要删除(断点下载的配置文件.position)
                    //如果存在断点配置.position文件,将其删除
                    file.delete();

                    raf.close();
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    //获取路径中的文件名
    private static String getFilename() {
        String filedir = path.substring(path.lastIndexOf("/") + 1);
        File sdcard = Environment.getExternalStorageDirectory();
        Log.i(TAG, sdcard.getPath()+"/" + filedir);
        return sdcard.getPath()+"/" + filedir;
    }
    
    //获取路径中的文件名
    private static String getFiledir() {
        File sdcard = Environment.getExternalStorageDirectory();
        return sdcard.getPath() + "/" ;
    }

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值