欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-23 23:17:52
android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到sd卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。 效果...

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多线程断点下载-带进度条和百分比进度显示效果就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。