首页 > 系统 > Android > 正文

android多线程断点下载-带进度条和百分比进度显示效果

2019-10-22 18:35:26
字体:
来源:转载
供稿:网友

android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到SD卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。

效果:

打开软件:

android,多线程,断点下载

下载中:

android,多线程,断点下载

下载完毕:

android,多线程,断点下载

附代码如下:

package com.yy.multiDownloadOfBreakPoint;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.view.View;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;/** * 多线程断点下载实例 * @author YUANYUAN * */public class MainActivity extends Activity {  //下载所使用的线程数  protected static final int threadCount = 3;  //下载完毕的标记  public static final int downloadOver = 1;  //更新下载进度标记  public static final int UPDATE_PROGRESS = 0;  //下载资源的路径输入框  private EditText et_path;  //下载的进度条  private ProgressBar pb;  //进度显示  private TextView tv_pb;  //当前累计下载的数据  int curDownCount=0;  //当前活动的下载线程数  protected static int activeThread;  //加入消息处理机制  private Handler handler=new Handler(){    @Override    public void handleMessage(Message msg) {      switch (msg.what) {      case downloadOver:        Toast.makeText(MainActivity.this, "文件已下载完毕!", Toast.LENGTH_LONG).show();        tv_pb.setText("下载完成");        break;      case UPDATE_PROGRESS:        //更新进度显示        tv_pb.setText("当前进度:"+(pb.getProgress()*100/pb.getMax())+"%");        break;      default:        break;      }    }  };  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    et_path=(EditText) findViewById(R.id.et_path);    et_path.setText("http://192.168.2.114:8080/sqlite.exe");    pb=(ProgressBar) findViewById(R.id.pb);    tv_pb=(TextView) findViewById(R.id.tv_pb);  }    /**   * 开始下载   * @param view   */  public void down(View view){    //获取下载资源的路径    final String path=et_path.getText().toString().trim();    //判断资源路径是否为空    if (TextUtils.isEmpty(path)) {      Toast.makeText(this, "请输入下载资源的路径", Toast.LENGTH_LONG).show();      return;    }    //开启一个线程进行下载    new Thread(){      public void run() {        try {          //构造URL地址          URL url=new URL(path);          //打开连接          HttpURLConnection conn=(HttpURLConnection) url.openConnection();          //设置请求超时的时间          conn.setConnectTimeout(5000);          //设置请求方式          conn.setRequestMethod("GET");          //获取相应码          int code=conn.getResponseCode();          if (code==200) {//请求成功            //获取请求数据的长度            int length=conn.getContentLength();            //设置进度条的最大值            pb.setMax(length);            //在客户端创建一个跟服务器文件大小相同的临时文件            RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");            //指定临时文件的长度            raf.setLength(length);            raf.close();            //假设3个线程去下载资源            //平均每一个线程要下载的文件的大小            int blockSize=length/threadCount;            for (int threadId = 1; threadId <= threadCount; threadId++) {              //当前线程下载数据的开始位置              int startIndex=blockSize*(threadId-1);              //当前线程下载数据的结束位置              int endIndex=blockSize*threadId-1;              //确定最后一个线程要下载数据的最大位置              if (threadId==threadCount) {                endIndex=length;              }              //显示下载数据的区间              System.out.println("线程【"+threadId+"】开始下载:"+startIndex+"---->"+endIndex);              //开启下载的子线程              new DownloadThread(path, threadId, startIndex, endIndex).start();              //当前下载活动的线程数加1              activeThread++;              System.out.println("当前活动的线程数:"+activeThread);            }                      }else{//请求失败            System.out.println("服务器异常,下载失败!");          }        } catch (Exception e) {          e.printStackTrace();          System.out.println("服务器异常,下载失败!");        }      };    }.start();      }  /**   * 下载文件的子线程 每一个文件都下载对应的数据   * @author YUANYUAN   *   */  public class DownloadThread extends Thread{    private String path;    private int threadId;    private int startIndex;    private int endIndex;        /**     * 构造方法     * @param path 下载文件的路径     * @param threadId 下载文件的线程     * @param startIndex 下载文件开始的位置     * @param endIndex 下载文件结束的位置     */    public DownloadThread(String path, int threadId, int startIndex,        int endIndex) {      this.path = path;      this.threadId = threadId;      this.startIndex = startIndex;      this.endIndex = endIndex;    }    @Override    public void run() {      //构造URL地址      try {                File tempFile=new File("sdcard/"+threadId+".txt");        //检查记录是否存在,如果存在读取数据,设置真实下载开始的位置        if (tempFile.exists()) {          FileInputStream fis=new FileInputStream(tempFile);          byte[] temp=new byte[1024];          int length=fis.read(temp);          //读取到已经下载的位置          int downloadNewIndex=Integer.parseInt(new String(temp, 0, length));          //计算出已经下载的数据长度          int areadyDown=downloadNewIndex-startIndex;          //累加已经下载的数据量          curDownCount+=areadyDown;          //设置进度条已经下载的数据量          pb.setProgress(curDownCount);          //设置重新开始下载的开始位置          startIndex=downloadNewIndex;          fis.close();          //显示真实下载数据的区间          System.out.println("线程【"+threadId+"】真实开始下载数据区间:"+startIndex+"---->"+endIndex);        }                URL url = new URL(path);        HttpURLConnection conn=(HttpURLConnection) url.openConnection();        conn.setConnectTimeout(5000);        conn.setRequestMethod("GET");        //设置请求属性,请求部分资源        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);        int code=conn.getResponseCode();        if (code==206) {//下载部分资源,正常返回的状态码为206          InputStream is=conn.getInputStream();//已经设置了请求的位置,所以返回的是对应的部分资源          //构建随机访问文件          RandomAccessFile raf=new RandomAccessFile("sdcard/setup.exe", "rwd");          //设置 每一个线程随机写文件开始的位置          raf.seek(startIndex);          //开始写文件          int len=0;          byte[] buffer=new byte[1024];          //该线程已经下载数据的长度          int total=0;                    while((len=is.read(buffer))!=-1){//读取输入流            //记录当前线程已下载数据的长度            RandomAccessFile file=new RandomAccessFile("sdcard/"+threadId+".txt","rwd");            raf.write(buffer,0,len);//写文件            total+=len;//更新该线程已下载数据的总长度            System.out.println("线程【"+threadId+"】已下载数据:"+(total+startIndex));            //将已下载数据的位置记录写入到文件            file.write((startIndex+total+"").getBytes());            //累加已经下载的数据量            curDownCount+=len;            //更新进度条【进度条的更新可以在非UI线程直接更新,具体见底层源代码】            pb.setProgress(curDownCount);                        //更新下载进度            Message msg=Message.obtain();            msg.what=UPDATE_PROGRESS;            handler.sendMessage(msg);                        file.close();          }          is.close();          raf.close();          //提示下载完毕          System.out.println("线程【"+threadId+"】下载完毕");        }      } catch (Exception e) {        e.printStackTrace();        System.out.println("线程【"+threadId+"】下载出现异常!!");      }finally{        //活动的线程数减少        activeThread--;        if (activeThread==0) {          for (int i = 1; i <= threadCount; i++) {            File tempFile=new File("sdcard/"+i+".txt");            tempFile.delete();          }          System.out.println("下载完毕,已清除全部临时文件");          //界面消息提示下载完毕          Message msg=new Message();          msg.what=downloadOver;          handler.sendMessage(msg);        }      }          }  }}

以上这篇android多线程断点下载-带进度条和百分比进度显示效果就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表