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程序设计有所帮助。