随笔,注释写得很清楚了,如有不明白的地方,相互交流.....
package com.download.service; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; /** * 下载线程 * @author dream * */ public class DownThread extends Thread { /** * 保存文件路径 */ private String filepath; /** * 停止线程标识 */ private boolean stopFlag=false; /** * 下载开始位置 */ private int startposition; /** * 下载结束位置 */ private int endposition; /** * 下载链接 */ private String url; /** * 下载服务类 */ private HttpDownService hds; /** * 线程下载完毕标识 */ private boolean success=false; /** * 当前线程下载量 */ private int currentjd=0; /** * 获取当前线程下载量 * @return */ public int getCurrentjd() { return currentjd; } /** * 当前线程是否下载完毕 * @return */ public boolean isSuccess() { return success; } @Override public void run() { BufferedReader br=null; RandomAccessFile fout=null; int oldposition=0; try{ File fstate=null; if(FileUtil.Exists(HttpDownService.DIR, this.getName()+".txt")){ fstate=FileUtil.createFile(HttpDownService.DIR, this.getName()+".txt"); br=new BufferedReader(new FileReader(fstate)); String line=br.readLine(); br.close(); if(line!=null){ line=line.trim(); //是否已完成下载 if("complete".equals(line)){ this.currentjd=endposition-startposition; this.success=true; return; }else{ int newposition=Integer.parseInt(line); //若当前开始位置大于下载开始位置则保存下载开始位置(用于计算下载量) if(newposition>startposition){ oldposition=startposition; startposition=newposition; } } } }else{ fstate=FileUtil.createFile(HttpDownService.DIR, this.getName()+".txt"); oldposition=startposition; } fout= new RandomAccessFile(this.filepath, "rwd"); fout.seek(startposition); HttpURLConnection http=DownUtil.getDownConnection(this.url, this.startposition, this.endposition); InputStream in= http.getInputStream(); byte[] buff=new byte[1024]; int len=0; while((len=in.read(buff, 0, 1024))>0){ success=false; if(stopFlag){ if(fout!=null){ fout.close(); return; } return; } fout.write(buff, 0, len); //当前线程下载进度 startposition=startposition+len; int jd=startposition-oldposition; //刷新当前进度消息 this.currentjd=jd; //把进度存储到存储设备中去 FileOutputStream fw=new FileOutputStream(fstate); fw.write((startposition+"").getBytes()); fw.close(); } //线程下载完毕 fout.close(); //将线程下载完毕信息写到磁盘 FileOutputStream fw=new FileOutputStream(fstate); fw.write(("complete").getBytes()); fw.close(); //下载完毕信号 this.success=true; //更新进度信息 this.currentjd=endposition-oldposition; }catch(Exception e){ throw new RuntimeException(e); }finally{ try{ if(fout!=null){ fout.close(); } }catch(Exception e){ throw new RuntimeException(e); } } } public DownThread(String randomFile,String threadName,int startposition,int endposition,String url,HttpDownService hds){ this.filepath=randomFile; this.setName(threadName); this.startposition=startposition; this.endposition=endposition; this.url=url; this.hds=hds; } /** * 停止下载线程 */ public void StopThread(){ this.stopFlag=true; } }
package com.download.service; import java.net.HttpURLConnection; import java.net.URL; /** * 计算各个线程下载开始和结束位置 * @author dream * */ public class DownUtil { public static long getContentLength(String url){ try{ HttpURLConnection http= DownUtil.getDownConnection(url); long len=http.getContentLength(); http.disconnect(); return len; }catch(Exception e){ throw new RuntimeException(e); } } /** * 获取Http连接 * @param url * @return */ public static HttpURLConnection getDownConnection(String url){ try{ URL hurl=new URL(url); HttpURLConnection http= (HttpURLConnection) hurl.openConnection(); http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; MALCJS)"); http.setRequestProperty("Connection", "Keep-Alive"); http.setRequestMethod("GET"); return http; }catch(Exception e){ throw new RuntimeException(e); } } /*** * 获取Http连接 * @param url * @param startposition * @param endposition * @return */ public static HttpURLConnection getDownConnection(String url,long startposition,long endposition){ try{ URL hurl=new URL(url); HttpURLConnection http= (HttpURLConnection) hurl.openConnection(); http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; InfoPath.3; MALCJS)"); http.setRequestProperty("Connection", "Keep-Alive"); http.setRequestMethod("GET"); http.setRequestProperty("Range", "bytes=" + startposition + "-"+ endposition); return http; }catch(Exception e){ throw new RuntimeException(e); } } }
package com.download.service; import java.io.File; import android.os.Environment; public class FileUtil { public static File createFile(String dir,String filename){ Environment ev=new Environment(); String diry= ev.getExternalStorageDirectory().getPath()+"/"+dir; File fdir=new File(diry); if(!fdir.exists()){ fdir.mkdirs(); } String path= ev.getExternalStorageDirectory().getPath()+"/"+dir+"/"+filename; File file=new File(path); try{ if(file.exists()){ return file; }else{ file.createNewFile(); return file; } }catch(Exception e){ throw new RuntimeException(e); } } public static boolean Exists(String dir,String filename){ Environment ev=new Environment(); String path= ev.getExternalStorageDirectory().getPath()+"/"+dir+"/"+filename; File file=new File(path); return file.exists(); } }
package com.download.service; import java.io.File; import java.util.ArrayList; import java.util.List; import android.os.Handler; /** * 多线程下载/断点续 * @author dream * */ public class HttpDownService { /** * 线程状态记录文件目录(处于SD卡) */ public static final String DIR="downtemp"; /** * 下载进度 */ private int jd=0; /** * 下载链接 */ private String url; /** * 总大小 */ private int total; /** * 获取总大小 * @return */ public int getTotal() { return total; } /** * 设置总大小 * @param total */ public void setTotal(int total) { this.total = total; } /** * 开启的下载线程数量(数量越多下载效率越高) */ private int threadcount; /** * 保存文件路径 */ private String filepath; /** * 下载线程集合 */ private List<DownThread> list; /** * 界面UI handler处理 */ private Handler handler; /** * 下载状态信息处理 */ private ProcessHandler ph; /** * 扫描下载状态的线程 */ private ScanThread st; public int getJd() { return this.jd; } public List<DownThread> getList() { return list; } /** * 设置当前下载进度(线程安全) * @param jd * @param oldjd */ public void setJd(int jd,int oldjd) { synchronized (this) { this.jd=this.jd-oldjd; this.jd = this.jd+ jd; } } public HttpDownService(String url,String filepath,Handler handler,ProcessHandler ph){ this.url=url; this.filepath=filepath; this.total=(int) DownUtil.getContentLength(url); this.handler=handler; this.ph=ph; } /*** * 启动下载 * @param threadCount */ public void StartDown(int threadCount){ this.threadcount=threadCount; if(this.list==null){ this.list=new ArrayList<DownThread>(); } this.list.clear(); int blocksize=this.total/this.threadcount; for(int i=0;i<this.threadcount;i++){ int startposition=i*blocksize; int endposition=(i+1)*blocksize; if(this.threadcount-i==1){ endposition=this.total; } DownThread dt=new DownThread(this.filepath, "e"+i, startposition,endposition, this.url, this); dt.start(); this.list.add(dt); } st=new ScanThread(this, this.handler, this.ph); st.start(); } /** * 停止下载 */ public void StopDown(){ for(DownThread dt:this.list){ dt.StopThread(); } this.st.StopThread(); } /** * 下载是否完成 * @return */ public boolean IsDownComplete(){ boolean ret=false; int i=0; for(DownThread dt:this.list){ if(dt.isSuccess()){ i++; } } if(this.threadcount==i){ ret=true; } return ret; } /** * 下载进度 * @return */ public int DownProcess(){ int process=0; for(DownThread dt:this.list){ process=process+dt.getCurrentjd(); } return process; } /** * 删除临时文件 */ public void DeleteStateFile(){ for(DownThread dt:this.list){ File file=FileUtil.createFile(HttpDownService.DIR, dt.getName()+".txt"); if(file.exists()){ file.delete(); } } } }
package com.download.service; import android.os.Handler; /** * 下载信息转发处理 * @author dream * */ public interface ProcessHandler { public void Process(Handler handler,int total,int current,boolean iscomplete); }
package com.download.service; import android.os.Handler; import android.os.Message; /** * 扫描下载状态,并转发状态信息 * @author dream * */ public class ScanThread extends Thread { /** * 下载服务类 */ private HttpDownService hds; /** * 界面UI Handler处理 */ private Handler handler; /** * 线程下载状态处理器 */ private ProcessHandler ph; /** * 停止线程标识 */ private boolean Stopflag=false; public ScanThread(HttpDownService hds,Handler handler,ProcessHandler ph){ this.handler=handler; this.hds=hds; this.ph=ph; } @Override public void run() { this.Stopflag=false; try{ while(!Stopflag){ Thread.sleep(10); this.ph.Process(this.handler, this.hds.getTotal(),this.hds.DownProcess(),this.hds.IsDownComplete()); //当所有线程下载完毕时,转发下载完毕信息 if(this.hds.IsDownComplete()){ this.ph.Process(this.handler, this.hds.getTotal(),this.hds.DownProcess(),this.hds.IsDownComplete()); this.hds.DeleteStateFile(); this.Stopflag=true; return; } } }catch(Exception e){ throw new RuntimeException(e); } } /** * 停止线程 */ public void StopThread(){ this.Stopflag=true; } }
效果图: