android多线程断点下载-带进度条和百分比进度显示效果
程序员文章站
2023-11-23 23:17:52
android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到sd卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。
效果...
android多线程断点下载,带进度条和百分比显示,断点下载的临时数据保存到sd卡的文本文档中,建议可以保存到本地数据库中,这样可以提高存取效率,从而提高系统性能。
效果:
打开软件:
下载中:
下载完毕:
附代码如下:
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多线程断点下载-带进度条和百分比进度显示效果就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
上一篇: 分享几个微博营销好方法