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

Android实现多线程断点下载的方法

程序员文章站 2023-02-02 11:27:35
本文实例讲述了android实现多线程断点下载的方法。分享给大家供大家参考。具体实现方法如下: package cn.itcast.download; imp...

本文实例讲述了android实现多线程断点下载的方法。分享给大家供大家参考。具体实现方法如下:

package cn.itcast.download; 
import java.io.file; 
import java.io.fileinputstream; 
import java.io.filenotfoundexception; 
import java.io.fileoutputstream; 
import java.io.ioexception; 
import java.io.inputstream; 
import java.io.randomaccessfile; 
import java.net.httpurlconnection; 
import java.net.malformedurlexception; 
import java.net.protocolexception; 
import java.net.url; 
import cn.itcast.mutiledownload.streamtool; 
import android.app.activity; 
import android.os.bundle; 
import android.os.handler; 
import android.os.message; 
import android.view.view; 
import android.view.view.onclicklistener; 
import android.widget.button; 
import android.widget.edittext; 
import android.widget.progressbar; 
import android.widget.textview; 
import android.widget.toast; 
public class mutiledownloadactivity 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())){ 
        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 (mutiledownloadactivity.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()); 
  } 
}

希望本文所述对大家的android程序设计有所帮助。